diff --git a/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateCreateDto.java b/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateCreateDto.java index cf2c9c983c16ee1555f22dcfa3b489cf96752c89..a6b4f1f7e183d139a19ef838f26ef27d14d5298d 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateCreateDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateCreateDto.java @@ -1,10 +1,11 @@ package org.fuseri.model.dto.certificate; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; -import org.fuseri.model.dto.course.CourseDto; +import org.fuseri.model.dto.course.CourseCertificateDto; import org.fuseri.model.dto.user.UserDto; @@ -12,6 +13,36 @@ import org.fuseri.model.dto.user.UserDto; * This class represents a Data Transfer Object (DTO) for creating Certificate entities. * It is used for creating Certificate entity. */ +@Schema(example = """ + { + "user": { + "id": 1, + "username": "adelkaxxx", + "email": "adelkaxxx@muni.mail.cz", + "firstName": "AdĂ©la", + "lastName": "Pulcová", + "address": { + "country": "Czechia", + "city": "Praha", + "street": "BubenskĂ© nábĹ™eĹľĂ", + "houseNumber": "306/13", + "zip": "170 00" + }, + "userType": "STUDENT", + "languageProficiency": { + "CZECH": "A2" + } + }, + "course": { + "id": 1, + "name": "english a1", + "capacity": 10, + "language": "ENGLISH", + "proficiency": "A1" + } + + } + """) @Getter @Setter public class CertificateCreateDto { @@ -20,9 +51,9 @@ public class CertificateCreateDto { private UserDto user; @NotNull @Valid - private CourseDto course; + private CourseCertificateDto course; - public CertificateCreateDto(UserDto user, CourseDto course) { + public CertificateCreateDto(UserDto user, CourseCertificateDto course) { this.user = user; this.course = course; } diff --git a/application/model/src/main/java/org/fuseri/model/dto/course/CourseCertificateDto.java b/application/model/src/main/java/org/fuseri/model/dto/course/CourseCertificateDto.java new file mode 100644 index 0000000000000000000000000000000000000000..8a7e5982f48e0b9edbd0e513eec26dafaca26c77 --- /dev/null +++ b/application/model/src/main/java/org/fuseri/model/dto/course/CourseCertificateDto.java @@ -0,0 +1,47 @@ +package org.fuseri.model.dto.course; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.fuseri.model.dto.common.DomainObjectDto; + +/** + * This class represents a Data Transfer Object (DTO) for Course entities. + * It is used for passing Course data to Certificate module. + * It extends the DomainObjectDto class and includes additional Course-specific fields. + */ +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +public class CourseCertificateDto extends DomainObjectDto { + + @NotBlank(message = "Course name is required") + @Size(max = 63, message = "Course name must not exceed {max} characters") + private String name; + + @NotNull(message = "Lecture capacity cannot be null") + @Min(value = 1, message = "Lecture capacity must be at least 1") + private Integer capacity; + + @NotNull(message = "Language type is required") + @Valid + private LanguageTypeDto language; + + @NotNull(message = "Proficiency level is required") + @Valid + private ProficiencyLevelDto proficiency; + + public CourseCertificateDto(String name, Integer capacity, LanguageTypeDto languageTypeDto, ProficiencyLevelDto proficiencyLevelDto) { + setId(0L); + this.name = name; + this.capacity = capacity; + this.language = languageTypeDto; + this.proficiency = proficiencyLevelDto; + } + +} diff --git a/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java b/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java index 711217d52682555b0a697d3b5682367ec2900309..a5aa263f9de41e0e3c2b6f442926a7bd8463f1c3 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java @@ -4,10 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import lombok.EqualsAndHashCode; +import lombok.*; import org.fuseri.model.dto.common.DomainObjectDto; -import lombok.Getter; -import lombok.Setter; import org.fuseri.model.dto.course.LanguageTypeDto; import org.fuseri.model.dto.course.ProficiencyLevelDto; @@ -36,6 +34,7 @@ import java.util.Map; @Getter @Setter @EqualsAndHashCode(callSuper = false) +@NoArgsConstructor public class UserDto extends DomainObjectDto { @NotBlank @@ -68,4 +67,16 @@ public class UserDto extends DomainObjectDto { this.address = address; this.userType = userType; } + + + public UserDto(String username, String email, String firstName, String lastName, AddressDto address, UserType userType,Map<LanguageTypeDto, ProficiencyLevelDto> languageProficiency) { + setId(0L); + this.username = username; + this.email = email; + this.firstName = firstName; + this.lastName = lastName; + this.address = address; + this.userType = userType; + this.languageProficiency = languageProficiency; + } } diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/Certificate.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/Certificate.java similarity index 98% rename from application/module-certificate/src/main/java/org/fuseri/modulecertificate/Certificate.java rename to application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/Certificate.java index 3b9b0a94666ab63b462e85c64e177f467769cb20..38c6b94678066cc9d7cf2626a97c94a72404a732 100644 --- a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/Certificate.java +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/Certificate.java @@ -1,4 +1,4 @@ -package org.fuseri.modulecertificate; +package org.fuseri.modulecertificate.certificate; import jakarta.persistence.*; diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateController.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateController.java similarity index 91% rename from application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateController.java rename to application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateController.java index e63254df618398a0faf40d7360551918cf9e5cdb..f7376d98019c7f6a4085efd77bcb9a70e36f0fb3 100644 --- a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateController.java +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateController.java @@ -1,9 +1,8 @@ -package org.fuseri.modulecertificate.service; +package org.fuseri.modulecertificate.certificate; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import jakarta.persistence.EntityNotFoundException; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import org.fuseri.model.dto.certificate.CertificateCreateDto; @@ -44,7 +43,7 @@ public class CertificateController { description = "Generates certificate, saves it into database and returns certificate information and certificate file.") @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Certificate generated successfully."), - @ApiResponse(responseCode = "400", description = "Invalid input.") + @ApiResponse(responseCode = "500", description = "Internal server error.") }) @PostMapping public ResponseEntity<CertificateSimpleDto> generate(@Valid @RequestBody CertificateCreateDto certificateCreateDto) { @@ -61,15 +60,12 @@ public class CertificateController { @Operation(summary = "Get a certificate by ID", description = "Returns a certificate with the specified ID.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Certificate with the specified ID retrieved successfully."), - @ApiResponse(responseCode = "404", description = "Certificate with the specified ID was not found.") + @ApiResponse(responseCode = "404", description = "Certificate with the specified ID was not found."), + @ApiResponse(responseCode = "400", description = "Invalid input.") }) @GetMapping("/{id}") public ResponseEntity<CertificateSimpleDto> find(@NotNull @PathVariable Long id) { - try { return ResponseEntity.ok(certificateFacade.findById(id)); - } catch (EntityNotFoundException e) { - return ResponseEntity.notFound().build(); - } } /** @@ -82,7 +78,7 @@ public class CertificateController { @Operation(summary = "Get certificates for user", description = "Returns certificates for given user in list.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Successfully retrieved certificates"), - @ApiResponse(responseCode = "400", description = "Invalid input."), + @ApiResponse(responseCode = "500", description = "Internal server error."), }) @GetMapping("/findForUser") public ResponseEntity<List<CertificateSimpleDto>> findForUser(@RequestParam Long userId) { @@ -101,6 +97,7 @@ public class CertificateController { description = "Returns certificates for given user and course in list.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Successfully retrieved certificates"), + @ApiResponse(responseCode = "500", description = "Internal server error."), @ApiResponse(responseCode = "400", description = "Invalid input."), }) @GetMapping("/findForUserAndCourse") @@ -116,6 +113,8 @@ public class CertificateController { @Operation(summary = "Delete a certificate with specified ID", description = "Deletes a certificate with the specified ID.") @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "Certificate with the specified ID deleted successfully."), + @ApiResponse(responseCode = "500", description = "Internal server error."), + @ApiResponse(responseCode = "400", description = "Invalid input.") }) @DeleteMapping("/{id}") public ResponseEntity<Void> delete(@NotNull @PathVariable Long id) { @@ -131,7 +130,7 @@ public class CertificateController { @Operation(summary = "Get certificates in paginated format", description = "Returns certificates in paginated format.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Successfully retrieved paginated certificates"), - @ApiResponse(responseCode = "400", description = "Invalid page number supplied"), + @ApiResponse(responseCode = "500", description = "Internal server error.") }) @GetMapping public ResponseEntity<Page<CertificateSimpleDto>> findAllCertificates(Pageable pageable) { diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateFacade.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateFacade.java similarity index 97% rename from application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateFacade.java rename to application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateFacade.java index 018c0591e6e30f92730d5cf7374fa26defca3b23..b3524b9779b200eac627f490eff73890d5ea531e 100644 --- a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateFacade.java +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateFacade.java @@ -1,4 +1,4 @@ -package org.fuseri.modulecertificate.service; +package org.fuseri.modulecertificate.certificate; import org.fuseri.model.dto.certificate.CertificateCreateDto; diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateMapper.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateMapper.java similarity index 90% rename from application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateMapper.java rename to application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateMapper.java index f6738c4428f97b4bb6cacf0b2806491aabf00e8b..f806843fb0b439d51b8d496dea091d956fd2de16 100644 --- a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateMapper.java +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateMapper.java @@ -1,9 +1,7 @@ -package org.fuseri.modulecertificate.service; +package org.fuseri.modulecertificate.certificate; import org.fuseri.model.dto.certificate.CertificateCreateDto; -import org.fuseri.model.dto.certificate.CertificateDto; import org.fuseri.model.dto.certificate.CertificateSimpleDto; -import org.fuseri.modulecertificate.Certificate; import org.mapstruct.Mapper; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateRepository.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateRepository.java similarity index 85% rename from application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateRepository.java rename to application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateRepository.java index 832d2d22d002b82e3a93287f4382cfa66273b56d..367431f98c3b62f1e883e165ba1c379c2f640aa8 100644 --- a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateRepository.java +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateRepository.java @@ -1,6 +1,5 @@ -package org.fuseri.modulecertificate.service; +package org.fuseri.modulecertificate.certificate; -import org.fuseri.modulecertificate.Certificate; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateService.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateService.java similarity index 94% rename from application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateService.java rename to application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateService.java index 245c88c35ea55f4d59d0d01ed2b15290fddc42ed..a32a659ca5f06da29e69190cc90503c8f47c27ff 100644 --- a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/CertificateService.java +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/certificate/CertificateService.java @@ -1,6 +1,5 @@ -package org.fuseri.modulecertificate.service; +package org.fuseri.modulecertificate.certificate; -import org.fuseri.modulecertificate.Certificate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiError.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiError.java new file mode 100644 index 0000000000000000000000000000000000000000..617a0da1509d27121fb234e12f901547a20fafb7 --- /dev/null +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiError.java @@ -0,0 +1,43 @@ +package org.fuseri.modulecertificate.exceptions; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.ToString; +import org.springframework.http.HttpStatus; + +import java.time.Clock; +import java.time.LocalDateTime; +import java.util.List; + +@Getter +@ToString +class ApiError { + + private HttpStatus status; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") + private LocalDateTime timestamp; + private String message; + private List<ApiSubError> subErrors; + private String path; + + private ApiError() { + timestamp = LocalDateTime.now(Clock.systemUTC()); + } + + ApiError(HttpStatus status, Throwable ex, String path) { + this(); + this.status = status; + this.path = path; + this.message = ex.getLocalizedMessage(); + } + + ApiError(HttpStatus status, List<ApiSubError> subErrors, Throwable ex, String path) { + this(); + this.status = status; + this.subErrors = subErrors; + this.path = path; + this.message = ex.getLocalizedMessage(); + } +} + + diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiSubError.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiSubError.java new file mode 100644 index 0000000000000000000000000000000000000000..f5ad2d920a83bfeb8157083b809af4cf0de3cc75 --- /dev/null +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiSubError.java @@ -0,0 +1,4 @@ +package org.fuseri.modulecertificate.exceptions; + +public interface ApiSubError { +} diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiValidationError.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiValidationError.java new file mode 100644 index 0000000000000000000000000000000000000000..43b6acd7e2baba228cdcbaf0a4e13f4b59cfaf76 --- /dev/null +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/ApiValidationError.java @@ -0,0 +1,19 @@ +package org.fuseri.modulecertificate.exceptions; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +@Data +@EqualsAndHashCode(callSuper = false) +@AllArgsConstructor +@Getter +@ToString +class ApiValidationError implements ApiSubError { + private String object; + private String field; + private Object rejectedValue; + private String message; +} diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/RestResponseEntityExceptionHandler.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..3161f0e18cc5be5e005110b135161879910a6b8b --- /dev/null +++ b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/exceptions/RestResponseEntityExceptionHandler.java @@ -0,0 +1,76 @@ +package org.fuseri.modulecertificate.exceptions; + +import jakarta.persistence.EntityNotFoundException; +import jakarta.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.util.UrlPathHelper; + +import java.util.List; + +@ControllerAdvice +public class RestResponseEntityExceptionHandler { + private static final UrlPathHelper URL_PATH_HELPER = new UrlPathHelper(); + + /** + * Handle ResourceNotFoundException exceptions + * + * @param ex exception + * @param request request + * @return response entity + */ + @ExceptionHandler(value = {EntityNotFoundException.class}) + public ResponseEntity<ApiError> handleNotFoundError(EntityNotFoundException ex, HttpServletRequest request) { + ApiError error = new ApiError( + HttpStatus.NOT_FOUND, + ex, + URL_PATH_HELPER.getRequestUri(request)); + return buildResponseEntity(error); + } + + /** + * Handle Validation exceptions + * + * @param ex exception + * @param request request + * @return response entity + */ + @ExceptionHandler(value = {MethodArgumentNotValidException.class, HttpMessageNotReadableException.class}) + public ResponseEntity<ApiError> handleValidationErrors(MethodArgumentNotValidException ex, HttpServletRequest request) { + List<ApiSubError> subErrors = ex.getBindingResult().getFieldErrors() + .stream() + .map(e -> (ApiSubError) new ApiValidationError(e.getObjectName(), e.getField(), e.getRejectedValue(), e.getDefaultMessage())) + .toList(); + ApiError error = new ApiError( + HttpStatus.BAD_REQUEST, + subErrors, + ex, + URL_PATH_HELPER.getRequestUri(request)); + return buildResponseEntity(error); + } + + /** + * Handle exceptions not matched by above handler methods + * + * @param ex exception + * @param request request + * @return response entity + */ + @ExceptionHandler({Exception.class}) + public ResponseEntity<ApiError> handleAll(final Exception ex, HttpServletRequest request) { + final ApiError error = new ApiError( + HttpStatus.INTERNAL_SERVER_ERROR, + ExceptionUtils.getRootCause(ex), + URL_PATH_HELPER.getRequestUri(request)); + return buildResponseEntity(error); + } + + private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) { + return new ResponseEntity<>(apiError, apiError.getStatus()); + } +} diff --git a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/ResourceNotFoundException.java b/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/ResourceNotFoundException.java deleted file mode 100644 index d24c445da1fcc4ba826a0e614778823400a4c719..0000000000000000000000000000000000000000 --- a/application/module-certificate/src/main/java/org/fuseri/modulecertificate/service/ResourceNotFoundException.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.fuseri.modulecertificate.service; - -public class ResourceNotFoundException extends RuntimeException { - public ResourceNotFoundException() { - } - - public ResourceNotFoundException(String message) { - super(message); - } - - public ResourceNotFoundException(String message, Throwable cause) { - super(message, cause); - } - - public ResourceNotFoundException(Throwable cause) { - super(cause); - } - - public ResourceNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateControllerTests.java b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateControllerTests.java index a74e9f10e84d11bdd60549886981f91d9d480025..77f5c3eec1edab3d80211e8004de540362c0fcfe 100644 --- a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateControllerTests.java +++ b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateControllerTests.java @@ -3,13 +3,13 @@ package org.fuseri.modulecertificate; import com.fasterxml.jackson.databind.ObjectMapper; import org.fuseri.model.dto.certificate.CertificateCreateDto; import org.fuseri.model.dto.certificate.CertificateSimpleDto; -import org.fuseri.model.dto.course.CourseDto; +import org.fuseri.model.dto.course.CourseCertificateDto; import org.fuseri.model.dto.course.LanguageTypeDto; import org.fuseri.model.dto.course.ProficiencyLevelDto; import org.fuseri.model.dto.user.AddressDto; import org.fuseri.model.dto.user.UserDto; import org.fuseri.model.dto.user.UserType; -import org.fuseri.modulecertificate.service.CertificateFacade; +import org.fuseri.modulecertificate.certificate.CertificateFacade; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; @@ -24,6 +24,7 @@ import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import java.time.Instant; +import java.util.HashMap; import java.util.List; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -35,8 +36,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. class CertificateControllerTests { private final UserDto USER = new UserDto("novakovat", - "novakova@gamil.com", "Tereza", "Nováková", new AddressDto(), UserType.STUDENT); - private final CourseDto COURSE = new CourseDto("AJ1", 10, + "novakova@gamil.com", "Tereza", "Nováková", + new AddressDto("USA", "New York", "Main Street", "123", "10001"), + UserType.STUDENT, new HashMap<>()); + private final CourseCertificateDto COURSE = new CourseCertificateDto("AJ1", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1); private final CertificateCreateDto certificateCreateDto = new CertificateCreateDto(USER, COURSE); private final CertificateSimpleDto certificateDto = new CertificateSimpleDto(0L, USER.getId(), @@ -56,9 +59,26 @@ class CertificateControllerTests { } } + @Test + void generateCertificate() throws Exception { + Mockito.when(certificateFacade.generate(ArgumentMatchers.any(CertificateCreateDto.class))) + .thenReturn(certificateDto); + + mockMvc.perform(post("/certificates") + .content(asJsonString(certificateCreateDto)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("$.id").value(certificateDto.getId())) + .andExpect(jsonPath("$.userId").value(certificateDto.getUserId())) + .andExpect(jsonPath("$.generatedAt").value(certificateDto.getGeneratedAt().toString())) + .andExpect(jsonPath("$.courseId").value(certificateDto.getCourseId())) + .andExpect(jsonPath("$.certificateFile").value(certificateDto.getCertificateFile())) + .andExpect(jsonPath("$.certificateFileName").value(certificateDto.getCertificateFileName())); + } + @Test void generateCertificateWithNullUser() throws Exception { - mockMvc.perform(post("/certificates/generate") + mockMvc.perform(post("/certificates") .content(asJsonString(new CertificateCreateDto(null, COURSE))) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is4xxClientError()); @@ -66,7 +86,7 @@ class CertificateControllerTests { @Test void generateCertificateWithNullCourse() throws Exception { - mockMvc.perform(post("/certificates/generate") + mockMvc.perform(post("/certificates") .content(asJsonString(new CertificateCreateDto(USER, null))) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is4xxClientError()); @@ -74,7 +94,7 @@ class CertificateControllerTests { @Test void generateCertificateWithoutParams() throws Exception { - mockMvc.perform(post("/certificates/generate") + mockMvc.perform(post("/certificates") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is4xxClientError()); } @@ -107,7 +127,7 @@ class CertificateControllerTests { @Test void findCertificatesWithoutUserId() throws Exception { mockMvc.perform(get("/certificates/findForUser")) - .andExpect(status().is4xxClientError()); + .andExpect(status().is5xxServerError()); } @Test @@ -128,20 +148,20 @@ class CertificateControllerTests { void findCertificateIdWithoutUserId() throws Exception { mockMvc.perform(get("/certificates/findForUserAndCourse") .param("courseId", "0")) - .andExpect(status().is4xxClientError()); + .andExpect(status().is5xxServerError()); } @Test void findCertificateIdWithoutCourseId() throws Exception { mockMvc.perform(get("/certificates/findForUserAndCourse") .param("userId", "0")) - .andExpect(status().is4xxClientError()); + .andExpect(status().is5xxServerError()); } @Test void findCertificateIdWithoutParams() throws Exception { mockMvc.perform(get("/certificates/findForUserAndCourse")) - .andExpect(status().is4xxClientError()); + .andExpect(status().is5xxServerError()); } @Test diff --git a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateFacadeTests.java b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateFacadeTests.java index 6875ef6247bd33155f98d8bf6c651cabc2fd0f04..99784c042c37a2f01d57045e2ccfc002c3c0cff2 100644 --- a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateFacadeTests.java +++ b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateFacadeTests.java @@ -2,15 +2,16 @@ package org.fuseri.modulecertificate; import org.fuseri.model.dto.certificate.CertificateCreateDto; import org.fuseri.model.dto.certificate.CertificateSimpleDto; -import org.fuseri.model.dto.course.CourseDto; +import org.fuseri.model.dto.course.CourseCertificateDto; import org.fuseri.model.dto.course.LanguageTypeDto; import org.fuseri.model.dto.course.ProficiencyLevelDto; import org.fuseri.model.dto.user.AddressDto; import org.fuseri.model.dto.user.UserDto; import org.fuseri.model.dto.user.UserType; -import org.fuseri.modulecertificate.service.CertificateFacade; -import org.fuseri.modulecertificate.service.CertificateMapper; -import org.fuseri.modulecertificate.service.CertificateService; +import org.fuseri.modulecertificate.certificate.Certificate; +import org.fuseri.modulecertificate.certificate.CertificateFacade; +import org.fuseri.modulecertificate.certificate.CertificateMapper; +import org.fuseri.modulecertificate.certificate.CertificateService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -34,7 +35,7 @@ import static org.mockito.Mockito.when; final class CertificateFacadeTests { private final UserDto USER = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto(), UserType.STUDENT); - private final CourseDto COURSE = new CourseDto("AJ1", 10, + private final CourseCertificateDto COURSE = new CourseCertificateDto("AJ1", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1); private final CertificateCreateDto certificateCreateDto = new CertificateCreateDto(USER, COURSE); private final CertificateSimpleDto certificateDto = new CertificateSimpleDto(0L, USER.getId(), diff --git a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateMapperTests.java b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateMapperTests.java index 00cf08aa380c2a3d068315df2bbd5119c7acb08d..7f66f907759c6ddeb9c0012cad1425147bad1cce 100644 --- a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateMapperTests.java +++ b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateMapperTests.java @@ -2,13 +2,14 @@ package org.fuseri.modulecertificate; import org.fuseri.model.dto.certificate.CertificateCreateDto; import org.fuseri.model.dto.certificate.CertificateSimpleDto; -import org.fuseri.model.dto.course.CourseDto; +import org.fuseri.model.dto.course.CourseCertificateDto; import org.fuseri.model.dto.course.LanguageTypeDto; import org.fuseri.model.dto.course.ProficiencyLevelDto; import org.fuseri.model.dto.user.AddressDto; import org.fuseri.model.dto.user.UserDto; import org.fuseri.model.dto.user.UserType; -import org.fuseri.modulecertificate.service.CertificateMapper; +import org.fuseri.modulecertificate.certificate.Certificate; +import org.fuseri.modulecertificate.certificate.CertificateMapper; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -26,7 +27,7 @@ final class CertificateMapperTests { private final UserDto USER = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto(), UserType.STUDENT); - private final CourseDto COURSE = new CourseDto("AJ1", 10, + private final CourseCertificateDto COURSE = new CourseCertificateDto("AJ1", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1); private final Instant instant = Instant.now(); private final String fileName = "fileName"; diff --git a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateRepositoryTests.java b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateRepositoryTests.java index 34ca57badbed1ae6a79c31b20ef4f810e40fc14c..08ae933b958fea4bfc16265c9bd209a6f443ddf7 100644 --- a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateRepositoryTests.java +++ b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateRepositoryTests.java @@ -1,6 +1,7 @@ package org.fuseri.modulecertificate; -import org.fuseri.modulecertificate.service.CertificateRepository; +import org.fuseri.modulecertificate.certificate.Certificate; +import org.fuseri.modulecertificate.certificate.CertificateRepository; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateServiceTests.java b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateServiceTests.java index dc11b78a1734722c0926a440e16329a8853bfeff..4ab79d90ffbd16c7bd4e521bc93e73d7ebbdcba9 100644 --- a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateServiceTests.java +++ b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/CertificateServiceTests.java @@ -6,8 +6,9 @@ import org.fuseri.model.dto.course.ProficiencyLevelDto; import org.fuseri.model.dto.user.AddressDto; import org.fuseri.model.dto.user.UserDto; import org.fuseri.model.dto.user.UserType; -import org.fuseri.modulecertificate.service.CertificateRepository; -import org.fuseri.modulecertificate.service.CertificateService; +import org.fuseri.modulecertificate.certificate.Certificate; +import org.fuseri.modulecertificate.certificate.CertificateRepository; +import org.fuseri.modulecertificate.certificate.CertificateService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired;