Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: feat pagination in get reactions API #99

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ class EmojiService(
// sort
if (emojiList.size != 0) {
emojiList.sortByDescending { it.created_at }
// pagination
emojiList = emojiList.subList(
min((index - 1) * count, emojiList.size - 1),
min(index * count, emojiList.size)
)
}
// pagination
emojiList = emojiList.subList(
min((index - 1) * count, emojiList.size - 1),
min(index * count, emojiList.size)
)
}
return emojiList
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ class ReactionController(private val reactionService: ReactionService) {
@GetMapping
fun getReactionsOfPost(
@RequestParam(value = "postId", defaultValue = "") postId: String,
@RequestParam(value = "emojiUnicode", defaultValue = "") emojiUnicode: String,
@RequestParam(value = "index", defaultValue = 1.toString()) index: Int,
@RequestParam(value = "count", defaultValue = 10.toString()) count: Int
): ResponseEntity<List<ReactionDto>> {
return ResponseEntity.ok(reactionService.getReactionsOfPost(postId))
return ResponseEntity.ok(reactionService.getReactionsOfPost(postId, emojiUnicode, index, count))
}

@PostMapping
fun postReaction(
@CurrentUser username: String,
@RequestParam(value = "postId", defaultValue = "") postId: String,
@RequestParam(value = "emojiId", defaultValue = "") emojiId: String

): ResponseEntity<Unit> {
return ResponseEntity(
reactionService.postReaction(username, postId, emojiId), HttpStatus.CREATED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import com.goliath.emojihub.springboot.domain.post.dao.PostDao
import com.goliath.emojihub.springboot.domain.reaction.dao.ReactionDao
import com.goliath.emojihub.springboot.domain.reaction.dto.ReactionDto
import com.goliath.emojihub.springboot.domain.user.dao.UserDao
import com.goliath.emojihub.springboot.global.exception.CustomHttp400
import com.goliath.emojihub.springboot.global.exception.CustomHttp403
import com.goliath.emojihub.springboot.global.exception.CustomHttp404
import com.goliath.emojihub.springboot.global.exception.ErrorType.BadRequest.INDEX_OUT_OF_BOUND
import com.goliath.emojihub.springboot.global.exception.ErrorType.BadRequest.COUNT_OUT_OF_BOUND
import com.goliath.emojihub.springboot.global.exception.ErrorType.Forbidden.USER_ALREADY_REACT
import com.goliath.emojihub.springboot.global.exception.ErrorType.Forbidden.REACTION_DELETE_FORBIDDEN
import com.goliath.emojihub.springboot.global.exception.ErrorType.NotFound.POST_NOT_FOUND
Expand All @@ -15,6 +18,7 @@ import com.goliath.emojihub.springboot.global.exception.ErrorType.NotFound.EMOJI
import com.goliath.emojihub.springboot.global.exception.ErrorType.NotFound.REACTION_NOT_FOUND
import com.goliath.emojihub.springboot.global.util.StringValue.ReactionField.POST_ID
import org.springframework.stereotype.Service
import java.lang.Integer.min

@Service
class ReactionService(
Expand All @@ -24,9 +28,31 @@ class ReactionService(
private val emojiDao: EmojiDao
) {

fun getReactionsOfPost(postId: String): List<ReactionDto> {
if (!postDao.existPost(postId)) throw CustomHttp404(POST_NOT_FOUND)
return reactionDao.getReactionsWithField(postId, POST_ID.string)
fun getReactionsOfPost(postId: String, emojiUnicode: String, index: Int, count: Int): List<ReactionDto> {
if (index <= 0) throw CustomHttp400(INDEX_OUT_OF_BOUND)
if (count <= 0) throw CustomHttp400(COUNT_OUT_OF_BOUND)
val post = postDao.getPost(postId) ?: throw CustomHttp404(POST_NOT_FOUND)
if (emojiUnicode == "") {
return reactionDao.getReactionsWithField(postId, POST_ID.string)
} else {
var reactionList = mutableListOf<ReactionDto>()
for (reactionWithEmojiUnicode in post.reactions) {
if (reactionWithEmojiUnicode.emoji_unicode != emojiUnicode)
continue
val reaction = reactionDao.getReaction(reactionWithEmojiUnicode.id) ?: continue
reactionList.add(reaction)
}
// sort
if (reactionList.size != 0) {
reactionList.sortByDescending { it.created_at }
// pagination
reactionList = reactionList.subList(
min((index - 1) * count, reactionList.size - 1),
min(index * count, reactionList.size)
)
}
return reactionList
}
}

fun postReaction(username: String, postId: String, emojiId: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.goliath.emojihub.springboot.domain.emoji.dto.PostEmojiRequest
import com.goliath.emojihub.springboot.domain.emoji.service.EmojiService
import com.goliath.emojihub.springboot.global.util.StringValue.UserField.CREATED_EMOJIS
import com.goliath.emojihub.springboot.global.util.StringValue.UserField.SAVED_EMOJIS
import org.hamcrest.Matchers
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Test

import org.junit.jupiter.api.DisplayName
Expand Down Expand Up @@ -64,7 +64,7 @@ internal class EmojiControllerTest @Autowired constructor(
// then
result.andExpect(status().isOk)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.length()", Matchers.equalTo(emojiList.size)))
.andExpect(jsonPath("$.length()", equalTo(emojiList.size)))
.andExpect(jsonPath("$[0].id").value(emojiList[0].id))
.andExpect(jsonPath("$[0].created_by").value(emojiList[0].created_by))
.andExpect(jsonPath("$[0].video_url").value(emojiList[0].video_url))
Expand Down Expand Up @@ -95,7 +95,7 @@ internal class EmojiControllerTest @Autowired constructor(
// then
result.andExpect(status().isOk)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.length()", Matchers.equalTo(emojiList.size)))
.andExpect(jsonPath("$.length()", equalTo(emojiList.size)))
.andExpect(jsonPath("$[0].id").value(emojiList[0].id))
.andExpect(jsonPath("$[0].created_by").value(emojiList[0].created_by))
.andExpect(jsonPath("$[0].video_url").value(emojiList[0].video_url))
Expand Down Expand Up @@ -126,7 +126,7 @@ internal class EmojiControllerTest @Autowired constructor(
// then
result.andExpect(status().isOk)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.length()", Matchers.equalTo(emojiList.size)))
.andExpect(jsonPath("$.length()", equalTo(emojiList.size)))
.andExpect(jsonPath("$[0].id").value(emojiList[0].id))
.andExpect(jsonPath("$[0].created_by").value(emojiList[0].created_by))
.andExpect(jsonPath("$[0].video_url").value(emojiList[0].video_url))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.goliath.emojihub.springboot.domain.WithCustomUser
import com.goliath.emojihub.springboot.domain.post.dto.PostDto
import com.goliath.emojihub.springboot.domain.post.dto.PostRequest
import com.goliath.emojihub.springboot.domain.post.service.PostService
import org.hamcrest.Matchers
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Test

import org.junit.jupiter.api.DisplayName
Expand Down Expand Up @@ -87,7 +87,7 @@ internal class PostControllerTest @Autowired constructor(
// then
result.andExpect(status().isOk)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.length()", Matchers.equalTo(postList.size)))
.andExpect(jsonPath("$.length()", equalTo(postList.size)))
.andExpect(jsonPath("$[0].id").value(postList[0].id))
.andExpect(jsonPath("$[0].created_by").value(postList[0].created_by))
.andExpect(jsonPath("$[0].content").value(postList[0].content))
Expand Down Expand Up @@ -123,7 +123,7 @@ internal class PostControllerTest @Autowired constructor(
// then
result.andExpect(status().isOk)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.length()", Matchers.equalTo(posts.size)))
.andExpect(jsonPath("$.length()", equalTo(posts.size)))
.andExpect(jsonPath("$[0].id").value(posts[0].id))
.andExpect(jsonPath("$[0].created_by").value(posts[0].created_by))
.andExpect(jsonPath("$[0].content").value(posts[0].content))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.goliath.emojihub.springboot.domain.TestDto
import com.goliath.emojihub.springboot.domain.WithCustomUser
import com.goliath.emojihub.springboot.domain.reaction.dto.ReactionDto
import com.goliath.emojihub.springboot.domain.reaction.service.ReactionService
import org.hamcrest.Matchers
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Test

import org.junit.jupiter.api.DisplayName
Expand Down Expand Up @@ -38,31 +38,38 @@ internal class ReactionControllerTest @Autowired constructor(
@DisplayName("게시글의 리액션 가져오기 테스트")
fun getReactionsOfPost() {
// given
val postId = reactionList[0].post_id
val post = testDto.postList[0]
val postId = post.id
val emojiUnicode = ""
val index = 1
val count = 10
val reactions = mutableListOf<ReactionDto>()
for (reaction in reactionList) {
if (reaction.post_id == postId) {
reactions.add(reaction)
}
}
Mockito.`when`(reactionService.getReactionsOfPost(postId)).thenReturn(reactions)
Mockito.`when`(reactionService.getReactionsOfPost(postId, emojiUnicode, index, count)).thenReturn(reactions)

// when
val result = this.mockMvc.perform(
get("/api/reaction")
.param("postId", postId)
.param("emojiUnicode", emojiUnicode)
.param("index", index.toString())
.param("count", count.toString())
)

// then
result.andExpect(status().isOk)
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.length()", Matchers.equalTo(reactions.size)))
.andExpect(jsonPath("$.length()", equalTo(reactions.size)))
.andExpect(jsonPath("$[0].id").value(reactions[0].id))
.andExpect(jsonPath("$[0].created_by").value(reactions[0].created_by))
.andExpect(jsonPath("$[0].post_id").value(reactions[0].post_id))
.andExpect(jsonPath("$[0].emoji_id").value(reactions[0].emoji_id))
.andExpect(jsonPath("$[0].created_at").value(reactions[0].created_at))
verify(reactionService, times(1)).getReactionsOfPost(postId)
verify(reactionService, times(1)).getReactionsOfPost(postId, emojiUnicode, index, count)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import com.goliath.emojihub.springboot.domain.post.dao.PostDao
import com.goliath.emojihub.springboot.domain.reaction.dao.ReactionDao
import com.goliath.emojihub.springboot.domain.reaction.dto.ReactionDto
import com.goliath.emojihub.springboot.domain.user.dao.UserDao
import com.goliath.emojihub.springboot.global.exception.CustomHttp400
import com.goliath.emojihub.springboot.global.exception.CustomHttp403
import com.goliath.emojihub.springboot.global.exception.CustomHttp404
import com.goliath.emojihub.springboot.global.exception.ErrorType.BadRequest.INDEX_OUT_OF_BOUND
import com.goliath.emojihub.springboot.global.exception.ErrorType.BadRequest.COUNT_OUT_OF_BOUND
import com.goliath.emojihub.springboot.global.exception.ErrorType.NotFound.USER_NOT_FOUND
import com.goliath.emojihub.springboot.global.exception.ErrorType.NotFound.POST_NOT_FOUND
import com.goliath.emojihub.springboot.global.exception.ErrorType.NotFound.EMOJI_NOT_FOUND
Expand Down Expand Up @@ -55,32 +58,70 @@ internal class ReactionServiceTest {
@DisplayName("게시글의 리액션 가져오기")
fun getReactionsOfPost() {
// given
val postId = testDto.postList[0].id
val post = testDto.postList[0]
val postId = post.id
val index = 1
val wrongIndex = 0
val count = 10
val wrongCount = 0
val emojiUnicodeAll = ""
val emojiUnicodeSpecific = if (post.reactions.size != 0) post.reactions[0].emoji_unicode else ""
val wrongId = "wrong_post_id"
val reactions = mutableListOf<ReactionDto>()
Mockito.`when`(postDao.existPost(postId)).thenReturn(true)
Mockito.`when`(postDao.existPost(wrongId)).thenReturn(false)
val reactionsAll = mutableListOf<ReactionDto>()
var reactionsSpecific = mutableListOf<ReactionDto>()
Mockito.`when`(postDao.getPost(postId)).thenReturn(post)
Mockito.`when`(postDao.getPost(wrongId)).thenReturn(null)
for (reactionWithEmojiUnicode in post.reactions) {
if (reactionWithEmojiUnicode.emoji_unicode != emojiUnicodeSpecific) continue
for (reaction in testDto.reactionList) {
if (reaction.id != reactionWithEmojiUnicode.id) continue
reactionsSpecific.add(reaction)
}
}
for (reaction in testDto.reactionList) {
if (reaction.post_id == postId) {
reactions.add(reaction)
reactionsAll.add(reaction)
}
}
Mockito.`when`(reactionDao.getReactionsWithField(postId, POST_ID.string)).thenReturn(reactions)
if (reactionsSpecific.size != 0) {
reactionsSpecific.sortByDescending { it.created_at }
reactionsSpecific = reactionsSpecific.subList(
Integer.min((index - 1) * count, reactionsSpecific.size - 1),
Integer.min(index * count, reactionsSpecific.size)
)
}
Mockito.`when`(reactionDao.getReactionsWithField(postId, POST_ID.string)).thenReturn(reactionsAll)
for (reaction in reactionsSpecific) {
Mockito.`when`(reactionDao.getReaction(reaction.id)).thenReturn(reaction)
}

// when
val result = reactionService.getReactionsOfPost(postId)
val assertThrows = assertThrows(CustomHttp404::class.java) {
reactionService.getReactionsOfPost(wrongId)
val result1 = reactionService.getReactionsOfPost(postId, emojiUnicodeAll, index, count)
val result2 = reactionService.getReactionsOfPost(postId, emojiUnicodeSpecific, index, count)
val assertThrows1 = assertThrows(CustomHttp400::class.java) {
reactionService.getReactionsOfPost(postId, emojiUnicodeAll, wrongIndex, count)
}
val assertThrows2 = assertThrows(CustomHttp400::class.java) {
reactionService.getReactionsOfPost(postId, emojiUnicodeAll, index, wrongCount)
}
val assertThrows3 = assertThrows(CustomHttp404::class.java) {
reactionService.getReactionsOfPost(wrongId, emojiUnicodeAll, index, count)
}

// then
assertAll(
{ assertEquals(result, reactions) },
{ assertEquals(assertThrows.message, POST_NOT_FOUND.getMessage()) }
{ assertEquals(result1, reactionsAll) },
{ assertEquals(result2, reactionsSpecific) },
{ assertEquals(assertThrows1.message, INDEX_OUT_OF_BOUND.getMessage()) },
{ assertEquals(assertThrows2.message, COUNT_OUT_OF_BOUND.getMessage()) },
{ assertEquals(assertThrows3.message, POST_NOT_FOUND.getMessage()) },
)
verify(postDao, times(1)).existPost(postId)
verify(postDao, times(1)).existPost(wrongId)
verify(postDao, times(2)).getPost(postId)
verify(postDao, times(1)).getPost(wrongId)
verify(reactionDao, times(1)).getReactionsWithField(postId, POST_ID.string)
for (reaction in reactionsSpecific) {
verify(reactionDao, times(1)).getReaction(reaction.id)
}
}

@Test
Expand Down