Skip to content

Commit

Permalink
Merge pull request #28 from jisung-in/feature/24-talkroom-comment-cre…
Browse files Browse the repository at this point in the history
…ate-api
  • Loading branch information
AHNYUNKI authored Mar 24, 2024
2 parents 6827d03 + b18c88f commit 020fcd2
Show file tree
Hide file tree
Showing 9 changed files with 362 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/main/java/com/jisungin/api/comment/CommentController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.jisungin.api.comment;

import com.jisungin.api.ApiResponse;
import com.jisungin.api.comment.request.CommentCreateRequest;
import com.jisungin.api.oauth.Auth;
import com.jisungin.api.oauth.AuthContext;
import com.jisungin.application.comment.CommentService;
import com.jisungin.application.comment.response.CommentResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RequestMapping("/v1")
@RestController
public class CommentController {

private final CommentService commentService;

@PostMapping("/talk-rooms/{talkRoomId}/comments")
public ApiResponse<CommentResponse> writeComment(@PathVariable Long talkRoomId,
@Valid @RequestBody CommentCreateRequest request,
@Auth AuthContext authContext) {
return ApiResponse.ok(commentService.writeComment(request.toService(), talkRoomId, authContext.getUserId()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.jisungin.api.comment.request;

import com.jisungin.application.comment.request.CommentCreateServiceRequest;
import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class CommentCreateRequest {

@NotBlank(message = "내용은 필수 입니다.")
private String content;

@Builder
private CommentCreateRequest(String content) {
this.content = content;
}

public CommentCreateServiceRequest toService() {
return CommentCreateServiceRequest.builder()
.content(content)
.build();
}

}
38 changes: 38 additions & 0 deletions src/main/java/com/jisungin/application/comment/CommentService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.jisungin.application.comment;

import com.jisungin.application.comment.request.CommentCreateServiceRequest;
import com.jisungin.application.comment.response.CommentResponse;
import com.jisungin.domain.comment.Comment;
import com.jisungin.domain.comment.repository.CommentRepository;
import com.jisungin.domain.talkroom.TalkRoom;
import com.jisungin.domain.talkroom.repository.TalkRoomRepository;
import com.jisungin.domain.user.User;
import com.jisungin.domain.user.repository.UserRepository;
import com.jisungin.exception.BusinessException;
import com.jisungin.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class CommentService {

private final CommentRepository commentRepository;
private final TalkRoomRepository talkRoomRepository;
private final UserRepository userRepository;

public CommentResponse writeComment(CommentCreateServiceRequest request, Long talkRoomId, Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND));

TalkRoom talkRoom = talkRoomRepository.findById(talkRoomId)
.orElseThrow(() -> new BusinessException(ErrorCode.TALK_ROOM_NOT_FOUND));

Comment comment = Comment.create(request, user, talkRoom);

commentRepository.save(comment);

return CommentResponse.of(comment.getContent(), user.getName());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.jisungin.application.comment.request;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class CommentCreateServiceRequest {

private String content;

@Builder
private CommentCreateServiceRequest(String content) {
this.content = content;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.jisungin.application.comment.response;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class CommentResponse {

private String content;

private String userName;

@Builder
private CommentResponse(String content, String userName) {
this.content = content;
this.userName = userName;
}

public static CommentResponse of(String content, String name) {
return CommentResponse.builder()
.content(content)
.userName(name)
.build();
}

}
9 changes: 9 additions & 0 deletions src/main/java/com/jisungin/domain/comment/Comment.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jisungin.domain.comment;

import com.jisungin.application.comment.request.CommentCreateServiceRequest;
import com.jisungin.domain.BaseEntity;
import com.jisungin.domain.talkroom.TalkRoom;
import com.jisungin.domain.user.User;
Expand Down Expand Up @@ -38,4 +39,12 @@ private Comment(User user, TalkRoom talkRoom, String content) {
this.content = content;
}

public static Comment create(CommentCreateServiceRequest request, User user, TalkRoom talkRoom) {
return Comment.builder()
.content(request.getContent())
.user(user)
.talkRoom(talkRoom)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.jisungin.domain.comment.repository;

import com.jisungin.domain.comment.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {

}
71 changes: 71 additions & 0 deletions src/test/java/com/jisungin/api/comment/CommentControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.jisungin.api.comment;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
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;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jisungin.api.comment.request.CommentCreateRequest;
import com.jisungin.application.comment.CommentService;
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.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;

@SpringBootTest
@AutoConfigureMockMvc
class CommentControllerTest {

@MockBean
CommentService commentService;

@Autowired
MockMvc mockMvc;

@Autowired
ObjectMapper objectMapper;

@Test
@DisplayName("유저가 토크방에 자신의 의견을 작성한다.")
void writeComment() throws Exception {
// given
CommentCreateRequest request = CommentCreateRequest.builder()
.content("의견을 작성하다")
.build();

// when // then
mockMvc.perform(post("/v1/talk-rooms/1/comments")
.content(objectMapper.writeValueAsString(request))
.contentType(APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value("200"))
.andExpect(jsonPath("$.status").value("OK"))
.andExpect(jsonPath("$.message").value("OK"));
}

@Test
@DisplayName("유저가 토크방에 자신의 의견을 남길 때 내용은 필수여야 한다.")
void writeCommentWithEmptyContent() throws Exception {
// given
CommentCreateRequest request = CommentCreateRequest.builder()
.build();

// when // then
mockMvc.perform(post("/v1/talk-rooms/1/comments")
.content(objectMapper.writeValueAsString(request))
.contentType(APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("400"))
.andExpect(jsonPath("$.message").value("내용은 필수 입니다."));
}

}
130 changes: 130 additions & 0 deletions src/test/java/com/jisungin/application/comment/CommentServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.jisungin.application.comment;

import static org.assertj.core.api.Assertions.assertThat;

import com.jisungin.application.comment.request.CommentCreateServiceRequest;
import com.jisungin.application.comment.response.CommentResponse;
import com.jisungin.domain.ReadingStatus;
import com.jisungin.domain.book.Book;
import com.jisungin.domain.book.repository.BookRepository;
import com.jisungin.domain.comment.repository.CommentRepository;
import com.jisungin.domain.oauth.OauthId;
import com.jisungin.domain.oauth.OauthType;
import com.jisungin.domain.talkroom.TalkRoom;
import com.jisungin.domain.talkroom.TalkRoomRole;
import com.jisungin.domain.talkroom.repository.TalkRoomRepository;
import com.jisungin.domain.talkroom.repository.TalkRoomRoleRepository;
import com.jisungin.domain.user.User;
import com.jisungin.domain.user.repository.UserRepository;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class CommentServiceTest {

@Autowired
TalkRoomRepository talkRoomRepository;

@Autowired
TalkRoomRoleRepository talkRoomRoleRepository;

@Autowired
CommentService commentService;

@Autowired
BookRepository bookRepository;

@Autowired
UserRepository userRepository;

@Autowired
CommentRepository commentRepository;

@AfterEach
void tearDown() {
commentRepository.deleteAllInBatch();
talkRoomRoleRepository.deleteAllInBatch();
talkRoomRepository.deleteAllInBatch();
userRepository.deleteAllInBatch();
bookRepository.deleteAllInBatch();
}

@Test
@DisplayName("유저가 1번 토크방에 자신의 의견 작성한다.")
void writeComment() {
// given
User user = createUser();
userRepository.save(user);

Book book = createBook();
bookRepository.save(book);

TalkRoom talkRoom = createTalkRoom(book, user);
talkRoomRepository.save(talkRoom);

createTalkRoomRole(talkRoom);

CommentCreateServiceRequest request = CommentCreateServiceRequest.builder()
.content("의견 남기기")
.build();
// when
CommentResponse response = commentService.writeComment(request, talkRoom.getId(), user.getId());

// then
assertThat(response)
.extracting("content", "userName")
.contains("의견 남기기", "[email protected]");
}

private void createTalkRoomRole(TalkRoom talkRoom) {
List<String> request = new ArrayList<>();
request.add("읽는 중");
request.add("읽음");

List<ReadingStatus> readingStatus = ReadingStatus.createReadingStatus(request);

readingStatus.stream().map(status -> TalkRoomRole.roleCreate(talkRoom, status))
.forEach(talkRoomRoleRepository::save);
}

private static TalkRoom createTalkRoom(Book book, User user) {
return TalkRoom.builder()
.book(book)
.title("토크방")
.content("내용")
.user(user)
.build();
}

private static User createUser() {
return User.builder()
.name("[email protected]")
.profileImage("image")
.oauthId(
OauthId.builder()
.oauthId("oauthId")
.oauthType(OauthType.KAKAO)
.build()
)
.build();
}

private static Book createBook() {
return Book.builder()
.title("제목")
.content("내용")
.authors("작가")
.isbn("11111")
.publisher("publisher")
.dateTime(LocalDateTime.now())
.imageUrl("www")
.build();
}

}

0 comments on commit 020fcd2

Please sign in to comment.