Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
import com.wcc.platform.repository.file.FileRepositoryException;
import jakarta.validation.ConstraintViolationException;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
Expand Down Expand Up @@ -100,4 +102,22 @@ public ResponseEntity<ErrorDetails> handleNotAcceptableError(
HttpStatus.NOT_ACCEPTABLE.value(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_ACCEPTABLE);
}

/**
* Receive {@link MethodArgumentNotValidException} for bean validation errors and return {@link
* HttpStatus#NOT_ACCEPTABLE}.
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<ErrorDetails> handleMethodArgumentNotValidException(
final MethodArgumentNotValidException ex, final WebRequest request) {
final var errorMessage =
ex.getBindingResult().getFieldErrors().stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.joining(", "));
final var errorDetails =
new ErrorDetails(
HttpStatus.BAD_REQUEST.value(), errorMessage, request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -85,7 +86,7 @@ public ResponseEntity<List<MentorDto>> getAllMentors() {
@PostMapping("/members")
@Operation(summary = "API to submit member registration")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<Member> createMember(@RequestBody final Member member) {
public ResponseEntity<Member> createMember(@Valid @RequestBody final Member member) {
return new ResponseEntity<>(memberService.createMember(member), HttpStatus.CREATED);
}

Expand All @@ -97,7 +98,7 @@ public ResponseEntity<Member> createMember(@RequestBody final Member member) {
@PostMapping("/mentors")
@Operation(summary = "API to submit mentor registration")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<Mentor> createMentor(@RequestBody final Mentor mentor) {
public ResponseEntity<Mentor> createMentor(@Valid @RequestBody final Mentor mentor) {
return new ResponseEntity<>(mentorshipService.create(mentor), HttpStatus.CREATED);
}

Expand All @@ -112,7 +113,7 @@ public ResponseEntity<Mentor> createMentor(@RequestBody final Mentor mentor) {
@Operation(summary = "API to update mentor data")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<Member> updateMentor(
@PathVariable final Long mentorId, @RequestBody final MentorDto mentorDto) {
@PathVariable final Long mentorId, @Valid @RequestBody final MentorDto mentorDto) {
return new ResponseEntity<>(mentorshipService.updateMentor(mentorId, mentorDto), HttpStatus.OK);
}

Expand All @@ -124,7 +125,7 @@ public ResponseEntity<Member> updateMentor(
@PostMapping("/mentees")
@Operation(summary = "API to submit mentee registration")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<Mentee> createMentee(@RequestBody final Mentee mentee) {
public ResponseEntity<Mentee> createMentee(@Valid @RequestBody final Mentee mentee) {
return new ResponseEntity<>(menteeService.create(mentee), HttpStatus.CREATED);
}

Expand All @@ -139,7 +140,7 @@ public ResponseEntity<Mentee> createMentee(@RequestBody final Mentee mentee) {
@Operation(summary = "API to update member data")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<Member> updateMember(
@PathVariable final Long memberId, @RequestBody final MemberDto memberDto) {
@PathVariable final Long memberId, @Valid @RequestBody final MemberDto memberDto) {
return new ResponseEntity<>(memberService.updateMember(memberId, memberDto), HttpStatus.OK);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.wcc.platform.domain.platform.member.Member;
import com.wcc.platform.domain.platform.member.ProfileStatus;
import com.wcc.platform.domain.platform.type.MemberType;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.Collections;
Expand All @@ -21,31 +20,31 @@
@SuppressWarnings({"PMD.ExcessiveParameterList", "PMD.ImmutableField"})
public class Mentee extends Member {

private @NotBlank MentorshipType prevMentorshipType;
private @NotBlank MentorshipType mentorshipType;
private @NotNull ProfileStatus profileStatus;
private @NotBlank Skills skills;
private @NotBlank String bio;
private MentorshipType prevMentorshipType;
@NotNull private MentorshipType mentorshipType;
@NotNull private ProfileStatus profileStatus;
@NotNull private Skills skills;
@NotBlank private String bio;
private List<String> spokenLanguages;

@Builder(builderMethodName = "menteeBuilder")
public Mentee(
final Long id,
@NotBlank final String fullName,
@NotBlank final String position,
@NotBlank @Email final String email,
@NotBlank final String slackDisplayName,
@NotBlank final Country country,
@NotBlank final String city,
final String fullName,
final String position,
final String email,
final String slackDisplayName,
final Country country,
final String city,
final String companyName,
final List<Image> images,
final List<SocialNetwork> network,
@NotNull final ProfileStatus profileStatus,
final List<String> spokenLanguages, // TODO
@NotBlank final String bio,
@NotBlank final Skills skills,
@NotBlank final MentorshipType mentorshipType,
@NotBlank final MentorshipType prevMentorshipType) {
final ProfileStatus profileStatus,
final List<String> spokenLanguages,
final String bio,
final Skills skills,
final MentorshipType mentorshipType,
final MentorshipType prevMentorshipType) {
super(
id,
fullName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.wcc.platform.domain.platform.mentorship.MentorDto.MentorDtoBuilder;
import com.wcc.platform.domain.platform.type.MemberType;
import com.wcc.platform.domain.resource.MentorResource;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.Collections;
Expand All @@ -30,11 +29,11 @@
@SuppressWarnings("PMD.ImmutableField")
public class Mentor extends Member {

private @NotBlank ProfileStatus profileStatus;
private @NotBlank Skills skills;
@NotNull private ProfileStatus profileStatus;
@NotNull private Skills skills;
private List<String> spokenLanguages;
private @NotBlank String bio;
private @NotNull MenteeSection menteeSection;
@NotBlank private String bio;
@NotNull private MenteeSection menteeSection;
private FeedbackSection feedbackSection;
private MentorResource resources;

Expand All @@ -43,20 +42,20 @@ public class Mentor extends Member {
@SuppressWarnings("PMD.ExcessiveParameterList")
public Mentor(
final Long id,
@NotBlank final String fullName,
@NotBlank final String position,
@NotBlank @Email final String email,
@NotBlank final String slackDisplayName,
@NotBlank final Country country,
@NotBlank final String city,
final String fullName,
final String position,
final String email,
final String slackDisplayName,
final Country country,
final String city,
final String companyName,
final List<Image> images,
final List<SocialNetwork> network,
@NotNull final ProfileStatus profileStatus,
final ProfileStatus profileStatus,
final List<String> spokenLanguages,
@NotBlank final String bio,
@NotBlank final Skills skills,
@NotBlank final MenteeSection menteeSection,
final String bio,
final Skills skills,
final MenteeSection menteeSection,
final FeedbackSection feedbackSection,
final MentorResource resources) {
super(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public MentorDto(
@NotBlank final String position,
@NotBlank @Email final String email,
@NotBlank final String slackDisplayName,
@NotBlank final Country country,
@NotNull final Country country,
@NotBlank final String city,
final String companyName,
final List<Image> images,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CONFLICT;

import com.wcc.platform.domain.exceptions.DuplicatedMemberException;
import com.wcc.platform.domain.exceptions.ErrorDetails;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.context.request.WebRequest;

class GlobalExceptionHandlerTest {
Expand All @@ -34,4 +40,28 @@ void givenHandleDuplicatedRecordWhenHandleDuplicatedRecordThenConsiderConflict()
assertEquals(CONFLICT, response.getStatusCode());
assertEquals(expectation, response.getBody());
}

@Test
@DisplayName(
"Given validation errors, when handling MethodArgumentNotValidException, then return NOT_ACCEPTABLE with error messages")
void shouldReturnNotAcceptableForMethodArgumentNotValidException() {
var bindingResult = mock(BindingResult.class);
var fieldError1 = new FieldError("object", "email", "must not be blank");
var fieldError2 = new FieldError("object", "name", "size must be between 1 and 100");
when(bindingResult.getFieldErrors()).thenReturn(List.of(fieldError1, fieldError2));

var exception = mock(MethodArgumentNotValidException.class);
when(exception.getBindingResult()).thenReturn(bindingResult);

var response =
globalExceptionHandler.handleMethodArgumentNotValidException(exception, webRequest);

var expectation =
new ErrorDetails(
BAD_REQUEST.value(),
"email: must not be blank, name: size must be between 1 and 100",
DETAILS);
assertEquals(BAD_REQUEST, response.getStatusCode());
assertEquals(expectation, response.getBody());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,48 @@
import com.wcc.platform.domain.platform.member.Member;
import com.wcc.platform.domain.platform.member.ProfileStatus;
import com.wcc.platform.domain.platform.mentorship.Mentee;
import com.wcc.platform.domain.platform.mentorship.MentorshipType;
import com.wcc.platform.domain.platform.mentorship.Skills;
import com.wcc.platform.domain.platform.type.MemberType;
import java.util.List;

/** Mentee test factories. */
public class SetupMenteeFactories {
/** Mentee Builder. */
public static Mentee createMenteeTest() {
final Member member = createMemberTest(MemberType.MENTEE);
return createMenteeTest(1L, member.getFullName(), member.getEmail());
}

/** Test factory for a Mentee. */
public static Mentee createMenteeTest(
final Long menteeId, final String name, final String email) {
final Member member = createMemberTest(MemberType.MENTEE);
/** Mentee Builder. */
public static Mentee createMenteeTest() {
final Member member = createMemberTest(MemberType.MENTEE);
return createMenteeTest(1L, member.getFullName(), member.getEmail());
}

Mentee.MenteeBuilder menteeBuilder =
Mentee.menteeBuilder()
.fullName(name)
.position(member.getPosition())
.email(email)
.companyName(member.getCompanyName())
.slackDisplayName(member.getSlackDisplayName())
.country(member.getCountry())
.city(member.getCity())
.images(member.getImages())
.profileStatus(ProfileStatus.ACTIVE)
.bio("Mentee bio")
.spokenLanguages(List.of("English"))
.skills(
new Skills(
2,
List.of(TechnicalArea.BACKEND, TechnicalArea.FRONTEND),
List.of(Languages.JAVASCRIPT),
List.of(MentorshipFocusArea.GROW_BEGINNER_TO_MID)));
if (menteeId != null) {
menteeBuilder.id(menteeId);
}
/** Test factory for a Mentee. */
public static Mentee createMenteeTest(
final Long menteeId, final String name, final String email) {
final Member member = createMemberTest(MemberType.MENTEE);

return menteeBuilder.build();
Mentee.MenteeBuilder menteeBuilder =
Mentee.menteeBuilder()
.fullName(name)
.position(member.getPosition())
.email(email)
.companyName(member.getCompanyName())
.slackDisplayName(member.getSlackDisplayName())
.country(member.getCountry())
.city(member.getCity())
.images(member.getImages())
.profileStatus(ProfileStatus.ACTIVE)
.bio("Mentee bio")
.spokenLanguages(List.of("English"))
.skills(
new Skills(
2,
List.of(TechnicalArea.BACKEND, TechnicalArea.FRONTEND),
List.of(Languages.JAVASCRIPT),
List.of(MentorshipFocusArea.GROW_BEGINNER_TO_MID)))
.mentorshipType(MentorshipType.AD_HOC);
if (menteeId != null) {
menteeBuilder.id(menteeId);
}

return menteeBuilder.build();
}
}
Loading