Skip to content

Commit

Permalink
Merge branch 'be' into dev-be/feature/codesquad-issue-team-05#80
Browse files Browse the repository at this point in the history
  • Loading branch information
DOEKYONG authored Aug 14, 2023
2 parents 452e86e + 8df6096 commit 65ba0ef
Show file tree
Hide file tree
Showing 9 changed files with 570 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,18 @@ public ApiResponse<List<CommentResponseDto>> getComments(@PathVariable Long issu
}

@PostMapping("/issues/{issueId}/comments")
public ApiResponse<String> save(@PathVariable Long issueId,
@RequestBody CommentRequestDto commentRequestDto,
HttpServletRequest request) {
commentService.save(request, issueId, commentRequestDto);
public ApiResponse<String> save(@PathVariable Long issueId, @RequestBody CommentRequestDto commentRequestDto,
HttpServletRequest request) {
Long userId = findUserIdByHttpRequest(request);
commentService.save(userId, issueId, commentRequestDto);

return ApiResponse.success(SUCCESS.getStatus(), SUCCESS.getMessage());
}

private Long findUserIdByHttpRequest(HttpServletRequest request) {
return Long.parseLong(String.valueOf(request.getAttribute("userId")));
}

@PatchMapping("/issues/comments/{commentId}")
public ApiResponse<String> modify(@PathVariable Long commentId,
@RequestBody CommentRequestDto commentRequestDto) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package codesquad.issueTracker.comment.dto;

import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -9,6 +10,7 @@
@AllArgsConstructor
public class CommentRequestDto {

@NotNull(message = "댓글 내용을 입력해주세요.")
private String content;

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import codesquad.issueTracker.global.exception.CustomException;
import codesquad.issueTracker.global.exception.ErrorCode;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -23,26 +22,25 @@ public List<CommentResponseDto> getComments(Long issueId) {
}

@Transactional
public Long save(HttpServletRequest request, Long issueId, CommentRequestDto commentRequestDto) {
Long userId = Long.parseLong(String.valueOf(request.getAttribute("userId")));
public Long save(Long userId, Long issueId, CommentRequestDto commentRequestDto) {
return commentRepository.create(userId, issueId, commentRequestDto)
.orElseThrow(() -> new CustomException(ErrorCode.DB_EXCEPTION));
.orElseThrow(() -> new CustomException(ErrorCode.FAILED_CREATE_COMMENT));
}

@Transactional
public Long modify(Long commentId, CommentRequestDto commentRequestDto) {
validateExistComment(commentId);
validateCommentStatus(commentId);
return commentRepository.update(commentId, commentRequestDto)
.orElseThrow(() -> new CustomException(ErrorCode.DB_EXCEPTION));
.orElseThrow(() -> new CustomException(ErrorCode.FAILED_UPDATE_COMMENT));
}

@Transactional
public Long delete(Long commentId) {
validateExistComment(commentId);
validateCommentStatus(commentId);
return commentRepository.deleteById(commentId)
.orElseThrow(() -> new CustomException(ErrorCode.DB_EXCEPTION));
.orElseThrow(() -> new CustomException(ErrorCode.FAILED_DELETE_COMMENT));
}

private Comment validateExistComment(Long commentId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@

public enum ErrorCode implements StatusCode {

REQUEST_VALIDATION_FAIL(HttpStatus.BAD_REQUEST),

// -- [Common] -- ]
DB_EXCEPTION(HttpStatus.SERVICE_UNAVAILABLE, "DB 서버 오류"),
REQUEST_VALIDATION_FAIL(HttpStatus.BAD_REQUEST),

// -- [OAuth] -- //
NOT_SUPPORTED_PROVIDER(HttpStatus.BAD_REQUEST, "지원하지 않는 로그인 방식입니다."),
Expand All @@ -32,10 +30,14 @@ public enum ErrorCode implements StatusCode {
ALREADY_EXIST_USER(HttpStatus.BAD_REQUEST, "이미 존재하는 유저입니다."),
NOT_FOUND_USER(HttpStatus.BAD_REQUEST, "해당하는 유저가 없습니다."),
FAILED_LOGIN_USER(HttpStatus.BAD_REQUEST, "로그인에 실패했습니다. 아이디, 비밀번호를 다시 입력해주세요. "),
FAILED_LOGOUT_USER(HttpStatus.SERVICE_UNAVAILABLE, "DB 서버 오류로 인해 사용자 로그아웃에 실패했습니다."),

// -- [Comment] -- //
NOT_EXIST_COMMENT(HttpStatus.BAD_REQUEST, "존재하지 않는 댓글입니다."),
ALREADY_DELETED_COMMENT(HttpStatus.BAD_REQUEST, "이미 삭제된 댓글입니다."),
FAILED_CREATE_COMMENT(HttpStatus.SERVICE_UNAVAILABLE, "DB 서버 오류로 인해 댓글 생성에 실패했습니다."),
FAILED_UPDATE_COMMENT(HttpStatus.SERVICE_UNAVAILABLE, "DB 서버 오류로 인해 댓글 수정에 실패했습니다."),
FAILED_DELETE_COMMENT(HttpStatus.SERVICE_UNAVAILABLE,"DB 서버 오류로 인해 댓글 삭제에 실패했습니다."),

// -- [Milestone] -- //
INVALIDATE_DATE(HttpStatus.BAD_REQUEST, "현재 날짜보다 이전 날짜 입니다."),
Expand All @@ -44,15 +46,16 @@ public enum ErrorCode implements StatusCode {
ILLEGAL_STATUS_MILESTONE(HttpStatus.BAD_REQUEST, "올바르지 않은 상태 입력 입니다."),

// -- [Label] -- //

LABEL_INSERT_FAILED(HttpStatus.BAD_REQUEST, "DB에서 라벨 생성에 실패했습니다."),
LABEL_UPDATE_FAILED(HttpStatus.BAD_REQUEST, "DB에서 라벨 수정에 실패했습니다."),
LABEL_DELETE_FAILED(HttpStatus.BAD_REQUEST, "DB에서 라벨 삭제에 실패했습니다"),
LABEL_FIND_FAILED(HttpStatus.BAD_REQUEST, "서버 오류로 라벨을 조회할 수 없습니다"),


// -- [Issue] -- //
DUPLICATE_OBJECT_FOUND(HttpStatus.BAD_REQUEST, "중복된 항목 선택입니다.");


private HttpStatus status;
private String message;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public ResponseAccessToken reissueAccessToken(RequestRefreshTokenDto refreshToke
public void logout(HttpServletRequest request) {
Long userId = Long.parseLong(String.valueOf(request.getAttribute("userId")));
userRepository.deleteTokenByUserId(userId)
.orElseThrow(() -> new CustomException(ErrorCode.DB_EXCEPTION));
.orElseThrow(() -> new CustomException(ErrorCode.FAILED_LOGOUT_USER));
}

public void validateUserIds(List<Long> assignees) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package codesquad.issueTracker.comment.controller;


import static codesquad.issueTracker.global.exception.SuccessCode.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import annotation.ControllerTest;
import codesquad.issueTracker.comment.dto.CommentRequestDto;
import codesquad.issueTracker.comment.dto.CommentResponseDto;
import codesquad.issueTracker.comment.fixture.CommentTestFixture;
import codesquad.issueTracker.comment.service.CommentService;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;


@ControllerTest(CommentController.class)
class CommentControllerTest extends CommentTestFixture {

private final Log log = LogFactory.getLog(CommentControllerTest.class);

private List<CommentResponseDto> commentResponseDtosFixture;
private CommentRequestDto commentRequestDtoFixture;

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@MockBean
private CommentService commentService;

@BeforeEach
public void setUp() {
commentResponseDtosFixture = dummyCommentResponseDtos();
commentRequestDtoFixture = dummyCommentRequestDto(1);
}

@Test
@DisplayName("모든 댓글 목록들을 반환한다.")
public void getComments() throws Exception {
//given
given(commentService.getComments(any())).willReturn(commentResponseDtosFixture);

//when
ResultActions resultActions = mockMvc.perform(get("/api/issues/{issueId}/comments", 1L));

//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value(SUCCESS.getStatus().getReasonPhrase()))
.andExpect(jsonPath("$.message[0].id").value(commentResponseDtosFixture.get(0).getId()))
.andExpect(jsonPath("$.message[0].createdAt").value(commentResponseDtosFixture.get(0).getCreatedAt().toString()))
.andExpect(jsonPath("$.message[0].content").value(commentResponseDtosFixture.get(0).getContent()))
.andExpect(jsonPath("$.message[0].writer.name").value(commentResponseDtosFixture.get(0).getWriter().getName()))
.andExpect(jsonPath("$.message[0].writer.profileImg").value(commentResponseDtosFixture.get(0).getWriter().getProfileImg()));
}

@Test
@DisplayName("이슈 댓글을 작성한다.")
public void save() throws Exception {
//given
given(commentService.save(any(), any(), any())).willReturn(1L);

//when
ResultActions resultActions = mockMvc.perform(post("/api/issues/{issueId}/comments", 1L)
.content(objectMapper.writeValueAsString(commentRequestDtoFixture))
.contentType(MediaType.APPLICATION_JSON)
.requestAttr("userId", 1L));

//then
resultActions.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value(SUCCESS.getStatus().getReasonPhrase()))
.andExpect(jsonPath("$.message").value(SUCCESS.getMessage()));
}

@Test
@DisplayName("이슈 댓글을 수정한다.")
public void modify() throws Exception {
//given
given(commentService.modify(any(), any())).willReturn(1L);

//when
ResultActions resultActions = mockMvc.perform(patch("/api/issues/comments/{commentId}", 1L)
.content(objectMapper.writeValueAsString(commentRequestDtoFixture))
.contentType(MediaType.APPLICATION_JSON));

//then
resultActions.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value(SUCCESS.getStatus().getReasonPhrase()))
.andExpect(jsonPath("$.message").value(SUCCESS.getMessage()));
}

@Test
@DisplayName("이슈 댓글을 삭제한다.")
public void delete() throws Exception {
//given
given(commentService.delete(any())).willReturn(1L);

//when
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete("/api/issues/comments/{commentId}", 1L));

//then
resultActions.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value(SUCCESS.getStatus().getReasonPhrase()))
.andExpect(jsonPath("$.message").value(SUCCESS.getMessage()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package codesquad.issueTracker.comment.fixture;

import codesquad.issueTracker.comment.domain.Comment;
import codesquad.issueTracker.comment.dto.CommentRequestDto;
import codesquad.issueTracker.comment.dto.CommentResponseDto;
import codesquad.issueTracker.comment.vo.CommentUserVo;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public abstract class CommentTestFixture {
public List<CommentResponseDto> dummyCommentResponseDtos() {
return IntStream.range(1, 4)
.mapToObj(this::makeCommentResponses)
.collect(Collectors.toList());
}

private CommentResponseDto makeCommentResponses(int num) {
Comment comment = dummyComment(num);
CommentUserVo commentUserVo = makeCommentUser();

return CommentResponseDto.builder()
.id((long) num)
.content(comment.getContent())
.writer(commentUserVo)
.createdAt(comment.getCreatedAt())
.build();
}

public Comment dummyComment(int num) {
return Comment.builder()
.issueId(1L)
.userId(1L)
.content("comment test" + num)
.createdAt(dummyLocalDateTime())
.build();
}

private LocalDateTime dummyLocalDateTime() {
return LocalDateTime.of(2023, 8, 12, 7, 23, 10);
}

private CommentUserVo makeCommentUser() {
return CommentUserVo.builder()
.name("sio")
.profileImg("http://image.png")
.build();
}

public CommentRequestDto dummyCommentRequestDto(int num) {
return new CommentRequestDto("comment test" + num);
}

public List<CommentRequestDto> dummyCommentRequestDtos() {
return IntStream.range(1, 4)
.mapToObj(this::dummyCommentRequestDto)
.collect(Collectors.toList());
}
}
Loading

0 comments on commit 65ba0ef

Please sign in to comment.