Skip to content

Commit

Permalink
Merge pull request #54 from vinho-notas/VIN-80-criar-PointScaleContro…
Browse files Browse the repository at this point in the history
…ller

Vin 80 criar point scale controller
  • Loading branch information
vanderleik authored Jan 26, 2024
2 parents cc539ef + 7b3e387 commit eb0316c
Show file tree
Hide file tree
Showing 5 changed files with 370 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import com.vinhonotas.avaliacao.domain.entities.PointScaleEntity;
import com.vinhonotas.avaliacao.interfaces.dtos.inputs.PointScaleInputDTO;
import com.vinhonotas.avaliacao.interfaces.dtos.outputs.PointScaleOutputDTO;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.UUID;

@Component
Expand Down Expand Up @@ -33,4 +35,36 @@ public PointScaleEntity toEntityUpdate(PointScaleInputDTO pointScaleInputDTO, UU
.pointScale(pointScaleInputDTO.getPointScale() != null ? pointScaleInputDTO.getPointScale() : pointScaleEntity.getPointScale())
.build();
}

public PointScaleOutputDTO toOutputDTO(PointScaleEntity pointScaleEntity) {
return PointScaleOutputDTO.builder()
.id(pointScaleEntity.getId())
.whatTasted(pointScaleEntity.getWhatTasted())
.whenTasted(pointScaleEntity.getWhenTasted())
.whatSaw(pointScaleEntity.getWhatSaw())
.whatAromas(pointScaleEntity.getWhatAromas())
.whatFlavors(pointScaleEntity.getWhatFlavors())
.whatOpinion(pointScaleEntity.getWhatOpinion())
.pointScale(pointScaleEntity.getPointScale())
.build();
}

public List<PointScaleOutputDTO> toOutputDTOList(List<PointScaleEntity> pointScaleEntityList) {
return pointScaleEntityList.stream()
.map(this::toOutputDTO)
.toList();
}

public PointScaleOutputDTO toOutputDTOUpdate(PointScaleEntity pointScaleEntity, UUID uuid, PointScaleOutputDTO pointScaleOutputDTO) {
return PointScaleOutputDTO.builder()
.id(uuid)
.whatTasted(pointScaleEntity.getWhatTasted() != null ? pointScaleEntity.getWhatTasted() : pointScaleOutputDTO.getWhatTasted())
.whenTasted(pointScaleEntity.getWhenTasted() != null ? pointScaleEntity.getWhenTasted() : pointScaleOutputDTO.getWhenTasted())
.whatSaw(pointScaleEntity.getWhatSaw() != null ? pointScaleEntity.getWhatSaw() : pointScaleOutputDTO.getWhatSaw())
.whatAromas(pointScaleEntity.getWhatAromas() != null ? pointScaleEntity.getWhatAromas() : pointScaleOutputDTO.getWhatAromas())
.whatFlavors(pointScaleEntity.getWhatFlavors() != null ? pointScaleEntity.getWhatFlavors() : pointScaleOutputDTO.getWhatFlavors())
.whatOpinion(pointScaleEntity.getWhatOpinion() != null ? pointScaleEntity.getWhatOpinion() : pointScaleOutputDTO.getWhatOpinion())
.pointScale(pointScaleEntity.getPointScale() != null ? pointScaleEntity.getPointScale() : pointScaleOutputDTO.getPointScale())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.vinhonotas.avaliacao.configuration;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfiguration {

public OpenAPI openApiInformation() {
Server localServer =
new Server()
.url("http://localhost:8082")
.description("Localhost Server URL");
Contact contact = new Contact()
.email("vanderlei.master@gmail.com")
.name("Vanderlei Kleinschmidt");
Info info = new Info()
.contact(contact)
.description("Api de cadastro de avaliação de vinhos")
.title("Api de vinho").version("V0.0.1")
.license(new License()
.name("Apache 2.0")
.url("http://springdoc.org"));

return new OpenAPI()
.info(info)
.addServersItem(localServer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.vinhonotas.avaliacao.interfaces.controllers;

import com.vinhonotas.avaliacao.application.converters.PointScaleConverter;
import com.vinhonotas.avaliacao.application.services.PointScaleService;
import com.vinhonotas.avaliacao.domain.entities.PointScaleEntity;
import com.vinhonotas.avaliacao.interfaces.dtos.inputs.PointScaleInputDTO;
import com.vinhonotas.avaliacao.interfaces.dtos.outputs.PointScaleOutputDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/v1/point-scales")
@Tag(name = "Point Scales", description = "Operações relacionadas a avaliação de vinhos")
public class PointScaleController {

private final PointScaleService pointScaleService;
private final PointScaleConverter pointScaleConverter;

@Operation(summary = "Cria uma avaliação de vinho")
@PostMapping
public ResponseEntity<PointScaleOutputDTO> createPointScale(@Valid @RequestBody PointScaleInputDTO pointScaleInputDTO) {
return ResponseEntity.ok(pointScaleConverter.toOutputDTO(pointScaleService.create(pointScaleInputDTO)));
}

@Operation(summary = "Retorna todas as avaliações de vinho")
@GetMapping
public ResponseEntity<List<PointScaleOutputDTO>> getAllPointScale() {
return ResponseEntity.ok(pointScaleConverter.toOutputDTOList(pointScaleService.getAll()));
}

@Operation(summary = "Retorna uma avaliação de vinho pelo id")
@GetMapping("/{id}")
public ResponseEntity<PointScaleOutputDTO> getPointScaleById(@PathVariable("id") String id) {
return ResponseEntity.ok(pointScaleConverter.toOutputDTO(pointScaleService.getById(UUID.fromString(id))));
}

@Operation(summary = "Atualiza uma avaliação de vinho pelo id")
@PutMapping("/{id}")
public ResponseEntity<PointScaleOutputDTO> updatePointScale(@PathVariable("id") String id, @Valid @RequestBody PointScaleInputDTO pointScaleInputDTO) {
PointScaleEntity pointScaleUpdated = pointScaleService.update(UUID.fromString(id), pointScaleInputDTO);
PointScaleOutputDTO pointScaleOutputDTO = pointScaleConverter.toOutputDTO(pointScaleUpdated);
return ResponseEntity.ok(pointScaleConverter.toOutputDTOUpdate(pointScaleUpdated, UUID.fromString(id), pointScaleOutputDTO));
}

@Operation(summary = "Deleta uma avaliação de vinho pelo id")
@DeleteMapping("/{id}")
public ResponseEntity<Void> deletePointScale(@PathVariable("id") String id) {
pointScaleService.delete(UUID.fromString(id));
return ResponseEntity.noContent().build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.vinhonotas.avaliacao.interfaces.dtos.outputs;

import com.vinhonotas.avaliacao.domain.enums.EnumPointScale;
import lombok.Builder;
import lombok.Data;

import java.util.UUID;

@Data
@Builder
public class PointScaleOutputDTO {

private UUID id;
private String whatTasted;
private String whenTasted;
private String whatSaw;
private String whatAromas;
private String whatFlavors;
private String whatOpinion;
private EnumPointScale pointScale;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package com.vinhonotas.avaliacao.interfaces.controllers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.vinhonotas.avaliacao.application.converters.PointScaleConverter;
import com.vinhonotas.avaliacao.application.services.PointScaleService;
import com.vinhonotas.avaliacao.application.services.exceptions.BadRequestException;
import com.vinhonotas.avaliacao.domain.entities.PointScaleEntity;
import com.vinhonotas.avaliacao.domain.enums.EnumPointScale;
import com.vinhonotas.avaliacao.interfaces.dtos.inputs.PointScaleInputDTO;
import com.vinhonotas.avaliacao.interfaces.dtos.outputs.PointScaleOutputDTO;
import com.vinhonotas.avaliacao.utils.MessagesConstants;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import java.util.List;
import java.util.UUID;

import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(controllers = PointScaleController.class)
class PointScaleControllerTest {

@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;

@MockBean
private PointScaleService pointScaleService;
@MockBean
private PointScaleConverter pointScaleConverter;

private PointScaleInputDTO pointScaleInputDTO;
private PointScaleOutputDTO pointScaleOutputDTO;
private PointScaleEntity pointScaleEntity;

@BeforeEach
void setUp() {
pointScaleInputDTO = createPointScaleInputDTO();
pointScaleOutputDTO = createPointScaleOutputDTO();
pointScaleEntity = createPointScaleEntity();
}

@Test
@DisplayName("Deve criar uma avaliação de vinho")
void testCreatePointScale() throws Exception {
when(pointScaleService.create(pointScaleInputDTO)).thenReturn(pointScaleEntity);
when(pointScaleConverter.toOutputDTO(pointScaleEntity)).thenReturn(pointScaleOutputDTO);

mockMvc.perform(post("/api/v1/point-scales")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pointScaleInputDTO)))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"));
}

@Test
@DisplayName("Deve retornar erro ao criar uma avaliação de vinho")
void testCreatePointScaleError() throws Exception {
when(pointScaleService.create(pointScaleInputDTO)).thenThrow(new BadRequestException(MessagesConstants.ERROR_CREATE_POINT_SCALE));

mockMvc.perform(post("/api/v1/point-scales")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pointScaleInputDTO)))
.andDo(print())
.andExpect(status().isBadRequest());
}

@Test
@DisplayName("Deve retornar uma lista de avaliações de vinho")
void testGetAllPointScale() throws Exception {
when(pointScaleService.getAll()).thenReturn(List.of(pointScaleEntity, pointScaleEntity));
when(pointScaleConverter.toOutputDTOList(List.of(pointScaleEntity, pointScaleEntity))).thenReturn(List.of(pointScaleOutputDTO, pointScaleOutputDTO));

mockMvc.perform(get("/api/v1/point-scales")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].id").value("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"));
}

@Test
@DisplayName("Deve retornar erro ao buscar uma lista de avaliações de vinho")
void testGetAllPointScaleError() throws Exception {
when(pointScaleService.getAll()).thenThrow(new BadRequestException(MessagesConstants.ERROR_POINT_SCALE_NOT_FOUND));

mockMvc.perform(get("/api/v1/point-scales")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isBadRequest());
}

@Test
@DisplayName("Deve retornar uma avaliação de vinho pelo id")
void testGetPointScaleById() throws Exception {
when(pointScaleService.getById(UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"))).thenReturn(pointScaleEntity);
when(pointScaleConverter.toOutputDTO(pointScaleEntity)).thenReturn(pointScaleOutputDTO);

mockMvc.perform(get("/api/v1/point-scales/{id}", "ea1cd995-e8d4-4cb7-b446-ca1a233aacba")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"));
}

@Test
@DisplayName("Deve retornar erro ao buscar uma avaliação de vinho pelo id")
void testGetPointScaleByIdError() throws Exception {
when(pointScaleService.getById(UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"))).thenThrow(
new BadRequestException(MessagesConstants.ERROR_POINT_SCALE_NOT_FOUND));

mockMvc.perform(get("/api/v1/point-scales/{id}", "ea1cd995-e8d4-4cb7-b446-ca1a233aacba")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isBadRequest());
}

@Test
@DisplayName("Deve atualizar uma avaliação de vinho pelo id")
void testUpdatePointScale() throws Exception {
pointScaleOutputDTO.setPointScale(EnumPointScale.NOTRECOMMENDED);

when(pointScaleService.update(UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"), pointScaleInputDTO)).thenReturn(pointScaleEntity);
when(pointScaleConverter.toOutputDTO(pointScaleEntity)).thenReturn(pointScaleOutputDTO);
when(pointScaleConverter.toOutputDTOUpdate(pointScaleEntity, UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"),
pointScaleOutputDTO)).thenReturn(pointScaleOutputDTO);

mockMvc.perform(put("/api/v1/point-scales/{id}", "ea1cd995-e8d4-4cb7-b446-ca1a233aacba")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pointScaleInputDTO)))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"))
.andExpect(jsonPath("$.pointScale").value(EnumPointScale.NOTRECOMMENDED.toString()));
}

@Test
@DisplayName("Deve retornar erro ao atualizar uma avaliação de vinho pelo id")
void testUpdatePointScaleError() throws Exception {
when(pointScaleService.update(UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"), pointScaleInputDTO)).thenThrow(
new BadRequestException(MessagesConstants.ERROR_UPDATE_POINT_SCALE));

mockMvc.perform(put("/api/v1/point-scales/{id}", "ea1cd995-e8d4-4cb7-b446-ca1a233aacba")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pointScaleInputDTO)))
.andDo(print())
.andExpect(status().isBadRequest());
}

@Test
@DisplayName("Deve deletar uma avaliação de vinho pelo id")
void testDeletePointScale() throws Exception {
mockMvc.perform(delete("/api/v1/point-scales/{id}", "ea1cd995-e8d4-4cb7-b446-ca1a233aacba")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isNoContent());
}

@Test
@DisplayName("Deve retornar erro ao deletar uma avaliação de vinho pelo id")
void testDeletePointScaleError() throws Exception {
doThrow(new BadRequestException(MessagesConstants.ERROR_DELETE_POINT_SCALE)).when(pointScaleService).delete(
UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"));
mockMvc.perform(delete("/api/v1/point-scales/{id}", "ea1cd995-e8d4-4cb7-b446-ca1a233aacba")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isBadRequest());
}

private PointScaleEntity createPointScaleEntity() {
return PointScaleEntity.builder()
.id(UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"))
.whatTasted("Faustino Rivero Ulecia Reserva Rioja DOCa, safra 2018, vinho tinto, seco, " +
"produzido e engarrafado por vinícola Loma Negra, em Vale Central, Chile.")
.whenTasted("Em 28/10/2023, às 21:30h.")
.whatSaw("Coloração amarelo dourado.")
.whatAromas("Aroma de pimentão vermelho maduro.")
.whatFlavors("Na boca boa acidez, lembrando frutas cítricas.")
.whatOpinion("Muito suculento com final longo.")
.pointScale(EnumPointScale.OUTSTANDING)
.build();
}

private PointScaleOutputDTO createPointScaleOutputDTO() {
return PointScaleOutputDTO.builder()
.id(UUID.fromString("ea1cd995-e8d4-4cb7-b446-ca1a233aacba"))
.whatTasted("Faustino Rivero Ulecia Reserva Rioja DOCa, safra 2018, vinho tinto, seco, " +
"produzido e engarrafado por vinícola Loma Negra, em Vale Central, Chile.")
.whenTasted("Em 28/10/2023, às 21:30h.")
.whatSaw("Coloração amarelo dourado.")
.whatAromas("Aroma de pimentão vermelho maduro.")
.whatFlavors("Na boca boa acidez, lembrando frutas cítricas.")
.whatOpinion("Muito suculento com final longo.")
.pointScale(EnumPointScale.OUTSTANDING)
.build();
}

private PointScaleInputDTO createPointScaleInputDTO() {
return PointScaleInputDTO.builder()
.whatTasted("Faustino Rivero Ulecia Reserva Rioja DOCa, safra 2018, vinho tinto, seco, " +
"produzido e engarrafado por vinícola Loma Negra, em Vale Central, Chile.")
.whenTasted("Em 28/10/2023, às 21:30h.")
.whatSaw("Coloração amarelo dourado.")
.whatAromas("Aroma de pimentão vermelho maduro.")
.whatFlavors("Na boca boa acidez, lembrando frutas cítricas.")
.whatOpinion("Muito suculento com final longo.")
.pointScale(EnumPointScale.OUTSTANDING)
.build();
}
}

0 comments on commit eb0316c

Please sign in to comment.