Skip to content

Commit

Permalink
[마이페이지] 내가 쓴 댓글 조회 및 삭제 (#88)
Browse files Browse the repository at this point in the history
* feat: 내 댓글 조회 및 삭제 기능 추가

* test: 내 댓글 조회 및 삭제 테스트 추가

* feat: Comment 가져오는 Query 수정

* fix: 변수 Naming 변경
  • Loading branch information
kkanggu authored Nov 5, 2023
1 parent 95955de commit 2c7f8ce
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.example.daitssuapi.domain.main.controller

import com.example.daitssuapi.common.dto.Response
import com.example.daitssuapi.domain.main.dto.request.CommentDeleteRequest
import com.example.daitssuapi.domain.main.dto.response.CommentResponse
import com.example.daitssuapi.domain.main.service.MyPageService
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/mypage")
class MyPageController(
private val myPageService: MyPageService
) {
@GetMapping("/{userId}/comments")
fun getComments(
@PathVariable userId: Long,
): Response<List<CommentResponse>> =
Response(data = myPageService.getComments(userId = userId))

@PatchMapping("/{userId}/comments")
fun deleteComments(
@PathVariable userId: Long,
@RequestBody request: CommentDeleteRequest
): Response<String> {
myPageService.deleteComments(commentIds = request.commentIds)

return Response(data = "Delete Ok")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.daitssuapi.domain.main.dto.request

data class CommentDeleteRequest(
val commentIds: List<Long>
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.daitssuapi.domain.main.dto.response

import com.example.daitssuapi.domain.main.model.entity.Comment
import java.time.LocalDateTime

data class CommentResponse(
Expand All @@ -9,4 +10,17 @@ data class CommentResponse(
val originalCommentId: Long? = null,
val createdAt: LocalDateTime,
val updatedAt: LocalDateTime
)
) {
companion object {
fun of(comment: Comment): CommentResponse = with(comment) {
CommentResponse(
commentId = id,
userId = writer.id,
content = content,
originalCommentId = originalId,
createdAt = createdAt,
updatedAt = updatedAt
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ class Comment(

val content: String,

val originalId: Long? = null
val originalId: Long? = null,

var isDeleted: Boolean = false
) : BaseEntity()
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ interface CommentRepository : JpaRepository<Comment, Long> {
fun findByNoticeId(noticeId: Long): List<Comment>

fun findByFunSystemId(funSystemId: Long): List<Comment>

fun findByWriterIdAndIsDeletedFalseOrderByIdDesc(userId: Long): List<Comment>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.example.daitssuapi.domain.main.service

import com.example.daitssuapi.common.enums.ErrorCode
import com.example.daitssuapi.common.exception.DefaultException
import com.example.daitssuapi.domain.main.dto.response.CommentResponse
import com.example.daitssuapi.domain.main.model.repository.CommentRepository
import com.example.daitssuapi.domain.main.model.repository.UserRepository
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class MyPageService(
private val commentRepository: CommentRepository,
private val userRepository: UserRepository
) {
fun getComments(userId: Long): List<CommentResponse> {
userRepository.findByIdOrNull(id = userId) ?: throw DefaultException(errorCode = ErrorCode.USER_NOT_FOUND)

return commentRepository.findByWriterIdAndIsDeletedFalseOrderByIdDesc(userId = userId).map {
CommentResponse.of(it)
}
}

@Transactional
fun deleteComments(commentIds: List<Long>) {
commentRepository.findAllById(commentIds).forEach {
it.isDeleted = true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class ArticleControllerTest(
@DisplayName("성공_올바른 정보를 넘겨줄 때_새로운 게시글을 스크랩한다")
fun newScrapSuccess() {
val userId = userRepository.findAll().sortedByDescending { it.id }[0].id
val articleId = commentRepository.findAll()[0].article.id
val articleId = commentRepository.findAll().filter { null != it.article }[0].id
val url = "/community/article/${articleId}/scrap"

mockMvc.perform(post(url)
Expand All @@ -217,7 +217,7 @@ class ArticleControllerTest(
@DisplayName("실패_신규 스크랩에서 isActive가 false라면_스크랩에 실패한다")
fun newScrapFailIsActiveFalse() {
val userId = userRepository.findAll().sortedByDescending { it.id }[0].id
val articleId = commentRepository.findAll()[0].article.id
val articleId = commentRepository.findAll().filter { null != it.article }[0].id
val url = "/community/article/${articleId}/scrap"

mockMvc.perform(post(url)
Expand All @@ -230,7 +230,7 @@ class ArticleControllerTest(
@DisplayName("실패_신규 스크랩에서 유저를 못 찾으면_스크랩에 실패한다")
fun newScrapFailNoUser() {
val userId = 0
val articleId = commentRepository.findAll()[0].article.id
val articleId = commentRepository.findAll().filter { null != it.article }[0].id
val url = "/community/article/${articleId}/scrap"

mockMvc.perform(post(url)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.example.daitssuapi.domain.main.controller

import com.example.daitssuapi.common.enums.ErrorCode
import com.example.daitssuapi.domain.main.dto.request.CommentDeleteRequest
import com.example.daitssuapi.domain.main.model.repository.CommentRepository
import com.example.daitssuapi.domain.main.model.repository.UserRepository
import com.example.daitssuapi.utils.ControllerTest
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.assertj.core.api.Assertions.*
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers

@ControllerTest
class MyPageControllerTest(
private val commentRepository: CommentRepository,
private val userRepository: UserRepository
) {
@Autowired
private lateinit var mockMvc: MockMvc

private val baseUrl = "/mypage"

@Test
@DisplayName("성공_자신의 userId를 넘겨줄 때_자신의 댓글이 조회된다")
fun successGetComments() {
val userId = commentRepository.findAll()[0].writer.id
val url = "$baseUrl/$userId/comments"

mockMvc.perform(
MockMvcRequestBuilders.get(url)
).andExpect(MockMvcResultMatchers.status().isOk)
}

@Test
@DisplayName("성공_자신의 userId를 넘겨줄 때_댓글이 없다면 조회되는 댓글이 없다")
fun successGetCommentsNoComments() {
val userIds = commentRepository.findAll().map { it.writer.id }
val userId = userRepository.findAll().filter { !userIds.contains(it.id) }[0].id
val url = "$baseUrl/$userId/comments"

mockMvc.perform(
MockMvcRequestBuilders.get(url)
).andExpect(MockMvcResultMatchers.status().isOk)
}

@Test
@DisplayName("실패_올바르지 않은 userId를 넘겨주면_댓글 조회에 실패한다")
fun failGetCommentsUserNotExist() {
val userId = 0
val url = "$baseUrl/$userId/comments"

mockMvc.perform(
MockMvcRequestBuilders.get(url)
).andExpect(MockMvcResultMatchers.status().isBadRequest)
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value(ErrorCode.USER_NOT_FOUND.code))
}

@Test
@DisplayName("성공_작성한 댓글을 넘겨줄 때_비활성화 상태가 된다")
fun successDeleteComments() {
val comments = commentRepository.findAll()
val userId = comments[0].writer.id
val commentDeleteRequest = CommentDeleteRequest(
commentIds = comments.filter { it.writer.id == userId }.filter { !it.isDeleted }.map { it.id }
)
val url = "$baseUrl/$userId/comments"
val request = jacksonObjectMapper().writeValueAsString(commentDeleteRequest)

mockMvc.perform(
MockMvcRequestBuilders.patch(url)
.content(request)
.contentType(MediaType.APPLICATION_JSON)
).andExpect(MockMvcResultMatchers.status().isOk)

comments.filter { it.writer.id == userId }.forEach { comment ->
assertThat(comment.isDeleted).isTrue()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class ArticleServiceTest(
@DisplayName("성공_올바른 정보를 넘겨줄 때_새로운 게시글을 스크랩한다")
fun newScrapSuccess() {
val userId = userRepository.findAll().sortedByDescending { it.id }[0].id
val articleId = commentRepository.findAll()[0].article.id
val articleId = commentRepository.findAll().filter { null != it.article }[0].id

articleService.scrapArticle(articleId = articleId, userId = userId, isActive = true)
}
Expand All @@ -197,7 +197,7 @@ class ArticleServiceTest(
@DisplayName("실패_신규 스크랩에서 isActive가 false라면_스크랩에 실패한다")
fun newScrapFailIsActiveFalse() {
val userId = userRepository.findAll().sortedByDescending { it.id }[0].id
val articleId = commentRepository.findAll()[0].article.id
val articleId = commentRepository.findAll().filter { null != it.article }[0].id

assertThrows<DefaultException> {
articleService.scrapArticle(
Expand All @@ -212,7 +212,7 @@ class ArticleServiceTest(
@DisplayName("실패_신규 스크랩에서 유저를 못 찾으면_스크랩에 실패한다")
fun newScrapFailNoUser() {
val userId = 0L
val articleId = commentRepository.findAll()[0].article.id
val articleId = commentRepository.findAll().filter { null != it.article }[0].id

assertThrows<DefaultException> {
articleService.scrapArticle(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.example.daitssuapi.domain.main.service

import com.example.daitssuapi.common.exception.DefaultException
import com.example.daitssuapi.domain.main.dto.request.CommentDeleteRequest
import com.example.daitssuapi.domain.main.model.repository.CommentRepository
import com.example.daitssuapi.domain.main.model.repository.UserRepository
import com.example.daitssuapi.utils.IntegrationTest
import org.assertj.core.api.Assertions.*
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows

@IntegrationTest
class MyPageServiceTest(
private val commentRepository: CommentRepository,
private val userRepository: UserRepository,
private val myPageService: MyPageService
) {
@Test
@DisplayName("성공_자신의 userId를 넘겨줄 때_자신의 댓글이 조회된다")
fun successGetComments() {
val comments = commentRepository.findAll()
val userId = comments[0].writer.id

val findComments = myPageService.getComments(userId = userId)

assertThat(findComments.size).isEqualTo(comments.filter { it.writer.id == userId }.filter { !it.isDeleted }.size)
}

@Test
@DisplayName("성공_자신의 userId를 넘겨줄 때_댓글이 없다면 조회되는 댓글이 없다")
fun successGetCommentsNoComments() {
val userIds = commentRepository.findAll().map { it.writer.id }
val userId = userRepository.findAll().filter { !userIds.contains(it.id) }[0].id

val findComments = myPageService.getComments(userId = userId)

assertThat(findComments.size).isZero
}

@Test
@DisplayName("실패_올바르지 않은 userId를 넘겨주면_댓글 조회에 실패한다")
fun failGetCommentsUserNotExist() {
val userId = 0L

assertThrows<DefaultException> { myPageService.getComments(userId = userId) }
}

@Test
@DisplayName("성공_작성한 댓글을 넘겨줄 때_비활성화 상태가 된다")
fun successDeleteComments() {
val comments = commentRepository.findAll()
val userId = comments[0].writer.id
val request = CommentDeleteRequest(
commentIds = comments.filter { it.writer.id == userId }.map { it.id }
)

myPageService.deleteComments(commentIds = request.commentIds)

comments.filter { it.writer.id == userId }.forEach { comment ->
assertThat(comment.isDeleted).isTrue()
}
}
}
9 changes: 5 additions & 4 deletions src/test/resources/h2-data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ INSERT INTO main.article(id, topic, title, content, user_id, created_at, updated
(2, 'QUESTION', '대충 제목2', '대충 내용1', 4, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000'),
(3, 'INFORMATION', '대충 제목3', '대충 내용1', 4, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000');

INSERT INTO main.comment(id, user_id, article_id, content, original_id, created_at, updated_at) VALUES
(1, 1, 1, '대충 댓글 쓴거1', null, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000'),
(2, 3, 1, '대충 대댓글 쓴거1', 1, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000'),
(3, 1, 3, '대충 댓글 쓴거2', null, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000');
INSERT INTO main.comment(id, user_id, article_id, content, original_id, is_deleted, created_at, updated_at) VALUES
(1, 1, 1, '대충 댓글 쓴거1', null, false, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000'),
(2, 3, 1, '대충 대댓글 쓴거1', 1, false, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000'),
(3, 1, 3, '대충 댓글 쓴거2', null, false, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000'),
(4, 1, 3, '대충 댓글 쓴거3', null, true, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000');

INSERT INTO main.scrap(id, user_id, article_id, is_active, created_at, updated_at) VALUES
(1, 1, 1, true, '2023-09-16 10:00:00.000', '2023-09-16 10:00:00.000'),
Expand Down

0 comments on commit 2c7f8ce

Please sign in to comment.