From a847331b097490992b7dd806b41dff87bd5632cc Mon Sep 17 00:00:00 2001 From: vladyslavpalamarchuk Date: Fri, 24 Feb 2023 19:59:31 +0200 Subject: [PATCH] [KNIG-17] - Create CRUD for new entity Reminder --- .../com/knighttodo/todocore/Constants.java | 3 +- .../todocore/domain/ReminderVO.java | 19 ++ .../InvalidReminderDateException.java | 5 + .../exception/ReminderNotFoundException.java | 13 ++ .../handling/GlobalExceptionHandler.java | 13 ++ .../todocore/rest/ReminderResource.java | 92 +++++++++ .../rest/mapper/ReminderRestMapper.java | 20 ++ .../request/CreateReminderRequestDto.java | 15 ++ .../request/UpdateReminderRequestDto.java | 15 ++ .../rest/response/ReminderResponseDto.java | 17 ++ .../todocore/service/ReminderService.java | 66 ++++++ .../privatedb/mapper/ReminderMapper.java | 13 ++ .../repository/ReminderRepository.java | 10 + .../privatedb/representation/Reminder.java | 45 ++++ .../todocore/factories/ReminderFactory.java | 29 +++ .../integration/ReminderIntegrationTest.java | 193 ++++++++++++++++++ 16 files changed, 567 insertions(+), 1 deletion(-) create mode 100644 todocore/src/main/java/com/knighttodo/todocore/domain/ReminderVO.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/exception/InvalidReminderDateException.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/exception/ReminderNotFoundException.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/rest/ReminderResource.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/rest/mapper/ReminderRestMapper.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/rest/request/CreateReminderRequestDto.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/rest/request/UpdateReminderRequestDto.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/rest/response/ReminderResponseDto.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/service/ReminderService.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/service/privatedb/mapper/ReminderMapper.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/service/privatedb/repository/ReminderRepository.java create mode 100644 todocore/src/main/java/com/knighttodo/todocore/service/privatedb/representation/Reminder.java create mode 100644 todocore/src/test/java/com/knighttodo/todocore/factories/ReminderFactory.java create mode 100644 todocore/src/test/java/com/knighttodo/todocore/integration/ReminderIntegrationTest.java diff --git a/todocore/src/main/java/com/knighttodo/todocore/Constants.java b/todocore/src/main/java/com/knighttodo/todocore/Constants.java index 8f5c62d..d9f4bb4 100644 --- a/todocore/src/main/java/com/knighttodo/todocore/Constants.java +++ b/todocore/src/main/java/com/knighttodo/todocore/Constants.java @@ -9,9 +9,10 @@ public class Constants { public static final String API_BASE_URL = "/api"; - public static final String API_BASE_URL_V1 = "/api/v1/"; + public static final String API_BASE_URL_V1 = "/api/v1"; public static final String API_BASE_TODOS = "/todos"; public static final String API_BASE_DAYS = "/days"; + public static final String API_BASE_REMINDER = "/reminders"; public static final String API_BASE_ROUTINES = "/routines"; public static final String API_BASE_ROUTINES_INSTANCES = "/routineInstances"; public static final String API_BASE_ROUTINES_TODO_INSTANCES = "/routineTodoInstances"; diff --git a/todocore/src/main/java/com/knighttodo/todocore/domain/ReminderVO.java b/todocore/src/main/java/com/knighttodo/todocore/domain/ReminderVO.java new file mode 100644 index 0000000..1f67c59 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/domain/ReminderVO.java @@ -0,0 +1,19 @@ +package com.knighttodo.todocore.domain; + +import lombok.Builder; +import lombok.Data; +import lombok.Value; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@Builder +public class ReminderVO { + + private UUID id; + private String name; + private String message; + private LocalDateTime reminderDate; +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/exception/InvalidReminderDateException.java b/todocore/src/main/java/com/knighttodo/todocore/exception/InvalidReminderDateException.java new file mode 100644 index 0000000..ea5f6f7 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/exception/InvalidReminderDateException.java @@ -0,0 +1,5 @@ +package com.knighttodo.todocore.exception; + +public class InvalidReminderDateException extends RuntimeException { + +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/exception/ReminderNotFoundException.java b/todocore/src/main/java/com/knighttodo/todocore/exception/ReminderNotFoundException.java new file mode 100644 index 0000000..344b93c --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/exception/ReminderNotFoundException.java @@ -0,0 +1,13 @@ +package com.knighttodo.todocore.exception; + +import lombok.extern.slf4j.Slf4j; + +import java.util.UUID; + +@Slf4j +public class ReminderNotFoundException extends RuntimeException { + + public ReminderNotFoundException(UUID id) { + log.warn("Reminder with id: {} not found", id); + } +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/exception/handling/GlobalExceptionHandler.java b/todocore/src/main/java/com/knighttodo/todocore/exception/handling/GlobalExceptionHandler.java index f6ed37d..8099fb3 100644 --- a/todocore/src/main/java/com/knighttodo/todocore/exception/handling/GlobalExceptionHandler.java +++ b/todocore/src/main/java/com/knighttodo/todocore/exception/handling/GlobalExceptionHandler.java @@ -1,5 +1,8 @@ package com.knighttodo.todocore.exception.handling; +import com.knighttodo.todocore.exception.InvalidReminderDateException; +import com.knighttodo.todocore.exception.ReminderNotFoundException; +import com.knighttodo.todocore.service.privatedb.representation.Reminder; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -14,6 +17,16 @@ @ControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + @ExceptionHandler({InvalidReminderDateException.class}) + public final ResponseEntity handleConflictException() { + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + @ExceptionHandler({ReminderNotFoundException.class}) + public final ResponseEntity handleNotFoundException(Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + @ExceptionHandler(RuntimeException.class) public final ResponseEntity handleCustomRuntimeException(RuntimeException ex, WebRequest request) { Throwable cause = ex.getCause() == null ? ex : ex.getCause(); diff --git a/todocore/src/main/java/com/knighttodo/todocore/rest/ReminderResource.java b/todocore/src/main/java/com/knighttodo/todocore/rest/ReminderResource.java new file mode 100644 index 0000000..43b55be --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/rest/ReminderResource.java @@ -0,0 +1,92 @@ +package com.knighttodo.todocore.rest; + +import com.knighttodo.todocore.domain.ReminderVO; +import com.knighttodo.todocore.rest.mapper.ReminderRestMapper; +import com.knighttodo.todocore.rest.request.CreateReminderRequestDto; +import com.knighttodo.todocore.rest.request.UpdateReminderRequestDto; +import com.knighttodo.todocore.rest.response.ReminderResponseDto; +import com.knighttodo.todocore.service.ReminderService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.util.UUID; + +import static com.knighttodo.todocore.Constants.API_BASE_REMINDER; +import static com.knighttodo.todocore.Constants.API_BASE_URL_V1; + +@Api(value = "ReminderResource controller") +@Slf4j +@RequiredArgsConstructor +@RestController +@RequestMapping(API_BASE_URL_V1 + API_BASE_REMINDER) +public class ReminderResource { + + private final ReminderRestMapper reminderRestMapper; + private final ReminderService reminderService; + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + @ApiOperation(value = "Add the new Reminder", response = ReminderResponseDto.class) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created"), + @ApiResponse(code = 409, message = "Invalid reminder date") + }) + public ReminderResponseDto addReminder(@Valid @RequestBody CreateReminderRequestDto requestDto) { + ReminderVO reminderVO = reminderRestMapper.toReminderVO(requestDto); + ReminderVO savedReminderVO = reminderService.save(reminderVO); + return reminderRestMapper.toReminderResponseDto(savedReminderVO); + } + + @PutMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + @ApiOperation(value = "Update the new Reminder", response = ReminderResponseDto.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Reminder successfully updated"), + @ApiResponse(code = 409, message = "Invalid reminder date") + }) + public ReminderResponseDto updateReminder(@Valid @RequestBody UpdateReminderRequestDto requestDto, + @PathVariable UUID id) { + ReminderVO reminderVO = reminderRestMapper.toReminderVO(requestDto); + ReminderVO updatedReminderVO = reminderService.update(id, reminderVO); + return reminderRestMapper.toReminderResponseDto(updatedReminderVO); + } + + @GetMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + @ApiOperation(value = "Get Reminder by id", response = ReminderResponseDto.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 404, message = "Reminder not found") + }) + public ReminderResponseDto getReminderById(@PathVariable UUID id) { + ReminderVO reminderVO = reminderService.findById(id); + return reminderRestMapper.toReminderResponseDto(reminderVO); + } + + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + @ApiOperation(value = "Delete Reminder by id") + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 404, message = "Reminder not found") + }) + public void deleteReminderById(@PathVariable UUID id) { + reminderService.deleteById(id); + } + +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/rest/mapper/ReminderRestMapper.java b/todocore/src/main/java/com/knighttodo/todocore/rest/mapper/ReminderRestMapper.java new file mode 100644 index 0000000..ae27404 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/rest/mapper/ReminderRestMapper.java @@ -0,0 +1,20 @@ +package com.knighttodo.todocore.rest.mapper; + +import com.knighttodo.todocore.domain.ReminderVO; +import com.knighttodo.todocore.rest.request.CreateReminderRequestDto; +import com.knighttodo.todocore.rest.request.UpdateReminderRequestDto; +import com.knighttodo.todocore.rest.response.ReminderResponseDto; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper(componentModel = "spring") +public interface ReminderRestMapper { + + @Mapping(target = "id", ignore = true) + ReminderVO toReminderVO(CreateReminderRequestDto requestDto); + + ReminderResponseDto toReminderResponseDto(ReminderVO savedReminderVO); + + @Mapping(target = "id", ignore = true) + ReminderVO toReminderVO(UpdateReminderRequestDto requestDto); +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/rest/request/CreateReminderRequestDto.java b/todocore/src/main/java/com/knighttodo/todocore/rest/request/CreateReminderRequestDto.java new file mode 100644 index 0000000..d602649 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/rest/request/CreateReminderRequestDto.java @@ -0,0 +1,15 @@ +package com.knighttodo.todocore.rest.request; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@Data +@Accessors(chain = true) +public class CreateReminderRequestDto { + + private String name; + private String message; + private LocalDateTime reminderDate; +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/rest/request/UpdateReminderRequestDto.java b/todocore/src/main/java/com/knighttodo/todocore/rest/request/UpdateReminderRequestDto.java new file mode 100644 index 0000000..7a37dc2 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/rest/request/UpdateReminderRequestDto.java @@ -0,0 +1,15 @@ +package com.knighttodo.todocore.rest.request; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@Data +@Accessors(chain = true) +public class UpdateReminderRequestDto { + + private String name; + private String message; + private LocalDateTime reminderDate; +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/rest/response/ReminderResponseDto.java b/todocore/src/main/java/com/knighttodo/todocore/rest/response/ReminderResponseDto.java new file mode 100644 index 0000000..1322e96 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/rest/response/ReminderResponseDto.java @@ -0,0 +1,17 @@ +package com.knighttodo.todocore.rest.response; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +@Accessors(chain = true) +public class ReminderResponseDto { + + private UUID id; + private String name; + private String message; + private LocalDateTime reminderDate; +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/service/ReminderService.java b/todocore/src/main/java/com/knighttodo/todocore/service/ReminderService.java new file mode 100644 index 0000000..f28d64b --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/service/ReminderService.java @@ -0,0 +1,66 @@ +package com.knighttodo.todocore.service; + +import com.knighttodo.todocore.domain.ReminderVO; +import com.knighttodo.todocore.exception.InvalidReminderDateException; +import com.knighttodo.todocore.exception.ReminderNotFoundException; +import com.knighttodo.todocore.service.privatedb.mapper.ReminderMapper; +import com.knighttodo.todocore.service.privatedb.repository.ReminderRepository; +import com.knighttodo.todocore.service.privatedb.representation.Reminder; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.UUID; + +@RequiredArgsConstructor +@Slf4j +@Service +@Transactional(readOnly = true) +public class ReminderService { + + private final ReminderRepository reminderRepository; + private final ReminderMapper reminderMapper; + + @Transactional + public ReminderVO save(ReminderVO reminderVO) { + validateReminderDate(reminderVO.getReminderDate()); + + Reminder reminder = reminderRepository.save(reminderMapper.toReminder(reminderVO)); + return reminderMapper.toReminderVO(reminder); + } + + public ReminderVO findById(UUID id) { + Reminder reminder = reminderRepository.findById(id) + .orElseThrow(() -> new ReminderNotFoundException(id)); + return reminderMapper.toReminderVO(reminder); + } + + @Transactional + public void deleteById(UUID id) { + Reminder reminder = reminderRepository.findById(id) + .orElseThrow(() -> new ReminderNotFoundException(id)); + + reminderRepository.delete(reminder); + } + + @Transactional + public ReminderVO update(UUID id, ReminderVO reminderVO) { + validateReminderDate(reminderVO.getReminderDate()); + reminderRepository.findById(id) + .orElseThrow(() -> new ReminderNotFoundException(id)); + + reminderVO.setId(id); + Reminder reminderToUpdate = reminderMapper.toReminder(reminderVO); + + return reminderMapper.toReminderVO(reminderRepository.save(reminderToUpdate)); + } + + private void validateReminderDate(LocalDateTime reminderDate) { + if (reminderDate.isBefore(LocalDateTime.now())) { + log.warn("Invalid reminder date: {}", reminderDate); + throw new InvalidReminderDateException(); + } + } +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/mapper/ReminderMapper.java b/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/mapper/ReminderMapper.java new file mode 100644 index 0000000..5d3f128 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/mapper/ReminderMapper.java @@ -0,0 +1,13 @@ +package com.knighttodo.todocore.service.privatedb.mapper; + +import com.knighttodo.todocore.domain.ReminderVO; +import com.knighttodo.todocore.service.privatedb.representation.Reminder; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface ReminderMapper { + + Reminder toReminder(ReminderVO reminderVO); + + ReminderVO toReminderVO(Reminder reminder); +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/repository/ReminderRepository.java b/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/repository/ReminderRepository.java new file mode 100644 index 0000000..10b28df --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/repository/ReminderRepository.java @@ -0,0 +1,10 @@ +package com.knighttodo.todocore.service.privatedb.repository; + +import com.knighttodo.todocore.service.privatedb.representation.Reminder; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface ReminderRepository extends JpaRepository { + +} diff --git a/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/representation/Reminder.java b/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/representation/Reminder.java new file mode 100644 index 0000000..7676604 --- /dev/null +++ b/todocore/src/main/java/com/knighttodo/todocore/service/privatedb/representation/Reminder.java @@ -0,0 +1,45 @@ +package com.knighttodo.todocore.service.privatedb.representation; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Entity +@Table(name = "reminder") +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class Reminder { + + @Id + @GeneratedValue + @Column(name = "id") + private UUID id; + + @Column(name = "name") + private String name; + + @Column(name = "message") + private String message; + + @Column(name = "date") + private LocalDateTime reminderDate; +} diff --git a/todocore/src/test/java/com/knighttodo/todocore/factories/ReminderFactory.java b/todocore/src/test/java/com/knighttodo/todocore/factories/ReminderFactory.java new file mode 100644 index 0000000..93e6fd0 --- /dev/null +++ b/todocore/src/test/java/com/knighttodo/todocore/factories/ReminderFactory.java @@ -0,0 +1,29 @@ +package com.knighttodo.todocore.factories; + +import com.knighttodo.todocore.rest.request.CreateReminderRequestDto; +import com.knighttodo.todocore.rest.request.UpdateReminderRequestDto; + +import java.time.LocalDateTime; + +public class ReminderFactory { + + public static final String NAME_CREATE = "Name to create"; + public static final String MESSAGE_CREATE = "Message to create"; + + public static final String NAME_UPDATE = "Name to update"; + public static final String MESSAGE_UPDATE = "Message to update"; + + public static CreateReminderRequestDto getCreateReminderRequestDto() { + return new CreateReminderRequestDto() + .setName(NAME_CREATE) + .setMessage(MESSAGE_CREATE) + .setReminderDate(LocalDateTime.now().plusDays(2)); + } + + public static UpdateReminderRequestDto getUpdateReminderRequestDto() { + return new UpdateReminderRequestDto() + .setName(NAME_UPDATE) + .setMessage(MESSAGE_UPDATE) + .setReminderDate(LocalDateTime.now().plusDays(2)); + } +} diff --git a/todocore/src/test/java/com/knighttodo/todocore/integration/ReminderIntegrationTest.java b/todocore/src/test/java/com/knighttodo/todocore/integration/ReminderIntegrationTest.java new file mode 100644 index 0000000..bae1f82 --- /dev/null +++ b/todocore/src/test/java/com/knighttodo/todocore/integration/ReminderIntegrationTest.java @@ -0,0 +1,193 @@ +package com.knighttodo.todocore.integration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.knighttodo.todocore.factories.ReminderFactory; +import com.knighttodo.todocore.rest.request.CreateReminderRequestDto; +import com.knighttodo.todocore.rest.request.UpdateReminderRequestDto; +import com.knighttodo.todocore.service.privatedb.repository.ReminderRepository; +import com.knighttodo.todocore.service.privatedb.representation.Reminder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.support.TestPropertySourceUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +import static com.knighttodo.todocore.Constants.API_BASE_REMINDER; +import static com.knighttodo.todocore.Constants.API_BASE_URL_V1; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +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.status; + +@SpringBootTest +@AutoConfigureMockMvc +@ContextConfiguration(initializers = ReminderIntegrationTest.DockerPostgreDataSourceInitializer.class) +@Testcontainers +public class ReminderIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private ReminderRepository reminderRepository; + + @AfterEach + public void tearDown() { + reminderRepository.deleteAll(); + } + + @Test + public void getReminderById_happyPath() throws Exception { + Reminder savedReminder = saveReminder(); + + getReminderById(savedReminder.getId()).andExpect(status().isOk()); + + Reminder reminder = reminderRepository.findById(savedReminder.getId()).orElse(null); + + assertThat(reminder).isNotNull(); + assertThat(reminder.getId()).isEqualTo(reminder.getId()); + assertThat(reminder.getName()).isNotNull(); + assertThat(reminder.getMessage()).isNotNull(); + assertThat(reminder.getReminderDate()).isNotNull(); + } + + @Test + public void getReminderById_whenNotFound_thenReturnNotFoundStatus() throws Exception { + saveReminder(); + getReminderById(UUID.randomUUID()).andExpect(status().isNotFound()); + } + + @Test + public void deleteReminderById_happyPath() throws Exception { + Reminder reminder = saveReminder(); + + deleteReminderById(reminder.getId()).andExpect(status().isOk()); + } + + @Test + public void deleteReminderById_whenNotFound_thenReturnNotFoundStatusCode() throws Exception { + saveReminder(); + deleteReminderById(UUID.randomUUID()).andExpect(status().isNotFound()); + } + + @Test + public void addReminder_whenCreateValidReminder_thenSaveSuccessfullyReminder() throws Exception { + CreateReminderRequestDto requestDto = ReminderFactory.getCreateReminderRequestDto(); + + createReminder(requestDto).andExpect(status().isCreated()); + + List reminders = reminderRepository.findAll(); + + assertThat(reminders.size()).isEqualTo(1); + + Reminder reminder = reminders.get(0); + assertThat(reminder.getName()).isEqualTo("Name to create"); + assertThat(reminder.getMessage()).isEqualTo("Message to create"); + assertThat(reminder.getReminderDate()).isNotNull(); + } + + @Test + public void addReminder_whenCreateReminderWithDateBeforeToday_thenSaveSuccessfullyReminder() throws Exception { + CreateReminderRequestDto requestDto = ReminderFactory.getCreateReminderRequestDto(); + requestDto.setReminderDate(LocalDateTime.now().minusDays(1)); + + createReminder(requestDto).andExpect(status().isConflict()); + } + + @Test + public void updateReminder_whenUpdateValidReminder_thenUpdateSuccessfullyReminder() throws Exception { + Reminder savedReminder = saveReminder(); + + UpdateReminderRequestDto requestDto = ReminderFactory.getUpdateReminderRequestDto(); + + updateReminder(requestDto, savedReminder.getId()).andExpect(status().isOk()); + + Reminder reminder = reminderRepository.findById(savedReminder.getId()).orElse(null); + + assertThat(reminder).isNotNull(); + assertThat(reminder.getId()).isEqualTo(reminder.getId()); + assertThat(reminder.getName()).isEqualTo("Name to update"); + assertThat(reminder.getMessage()).isEqualTo("Message to update"); + assertThat(reminder.getReminderDate()).isNotNull(); + } + + @Test + public void updateReminder_whenUpdateReminderWithDateBeforeToday_thenUpdateSuccessfullyReminder() throws Exception { + Reminder savedReminder = saveReminder(); + + UpdateReminderRequestDto requestDto = ReminderFactory.getUpdateReminderRequestDto(); + requestDto.setReminderDate(LocalDateTime.now().minusDays(1)); + + updateReminder(requestDto, savedReminder.getId()).andExpect(status().isConflict()); + } + + private ResultActions deleteReminderById(UUID id) throws Exception { + return mockMvc.perform(delete(API_BASE_URL_V1 + API_BASE_REMINDER + "/" + id) + .contentType(MediaType.APPLICATION_JSON_VALUE)); + } + + private ResultActions getReminderById(UUID id) throws Exception { + return mockMvc.perform(get(API_BASE_URL_V1 + API_BASE_REMINDER + "/" + id) + .contentType(MediaType.APPLICATION_JSON_VALUE)); + } + + private ResultActions createReminder(CreateReminderRequestDto requestDto) throws Exception { + return mockMvc.perform(post(API_BASE_URL_V1 + API_BASE_REMINDER) + .content(objectMapper.writeValueAsString(requestDto)) + .contentType(MediaType.APPLICATION_JSON_VALUE)); + } + + private ResultActions updateReminder(UpdateReminderRequestDto requestDto, UUID reminderId) throws Exception { + return mockMvc.perform(put(API_BASE_URL_V1 + API_BASE_REMINDER + "/" + reminderId) + .content(objectMapper.writeValueAsString(requestDto)) + .contentType(MediaType.APPLICATION_JSON_VALUE)); + } + + private Reminder saveReminder() { + return reminderRepository.save(Reminder.builder() + .name("old name") + .message("old message") + .reminderDate(LocalDateTime.now().plusDays(1)) + .build()); + } + + @Container + public static PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer<>("postgres:13.2"); + + static { + postgresqlContainer.start(); + } + + public static class DockerPostgreDataSourceInitializer implements ApplicationContextInitializer { + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + + TestPropertySourceUtils.addInlinedPropertiesToEnvironment( + applicationContext, + "spring.datasource.url=" + postgresqlContainer.getJdbcUrl(), + "spring.datasource.username=" + postgresqlContainer.getUsername(), + "spring.datasource.password=" + postgresqlContainer.getPassword() + ); + } + } +}