Skip to content
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
2 changes: 1 addition & 1 deletion src/docs/asciidoc/votes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[[투표-현황-조회]]
=== `GET` 투표 현황 조회

operation::vote-controller-test/find-vote-status[snippets='http-request,curl-request,request-headers,path-parameters,http-response,response-fields']
operation::vote-controller-test/find-vote-result[snippets='http-request,curl-request,request-headers,path-parameters,http-response,response-fields']

[[투표]]
=== `POST` 투표
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.chooz.post.domain.PollChoice;
import com.chooz.post.domain.Post;
import com.chooz.vote.domain.Vote;
import com.chooz.vote.presentation.dto.VoteStatusResponse;
import com.chooz.vote.presentation.dto.VoteResultResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

Expand All @@ -14,16 +14,16 @@

@Component
@RequiredArgsConstructor
public class VoteStatusReader {
public class VoteResultReader {

private final RatioCalculator ratioCalculator;

public List<VoteStatusResponse> getVoteStatus(List<Vote> totalVoteList, Post post) {
public List<VoteResultResponse> getVoteResult(List<Vote> totalVoteList, Post post) {
int totalVoteCount = totalVoteList.size();
Map<PollChoice, Long> pollChoiceVoteCountMap = getPollChoiceVoteCountMap(totalVoteList, post);
return pollChoiceVoteCountMap.entrySet().stream()
.map(entry -> getPollChoiceStatusResponse(entry, totalVoteCount))
.sorted(Comparator.comparingLong(VoteStatusResponse::voteCount).reversed())
.map(entry -> getVoteResultResponse(entry, totalVoteCount))
.sorted(Comparator.comparingLong(VoteResultResponse::voteCount).reversed())
.toList();
}

Expand All @@ -37,11 +37,11 @@ private Map<PollChoice, Long> getPollChoiceVoteCountMap(List<Vote> totalVoteList
));
}

private VoteStatusResponse getPollChoiceStatusResponse(Map.Entry<PollChoice, Long> entry, int totalVoteCount) {
private VoteResultResponse getVoteResultResponse(Map.Entry<PollChoice, Long> entry, int totalVoteCount) {
PollChoice pollChoice = entry.getKey();
Long voteCount = entry.getValue();
String ratio = ratioCalculator.calculate(totalVoteCount, voteCount);
return new VoteStatusResponse(
return new VoteResultResponse(
pollChoice.getId(),
pollChoice.getTitle(),
pollChoice.getImageUrl(),
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/chooz/vote/application/VoteService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.chooz.post.domain.PostRepository;
import com.chooz.vote.domain.Vote;
import com.chooz.vote.domain.VoteRepository;
import com.chooz.vote.presentation.dto.VoteStatusResponse;
import com.chooz.vote.presentation.dto.VoteResultResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -23,7 +23,7 @@ public class VoteService {
private final PostRepository postRepository;
private final EventPublisher eventPublisher;
private final VoteValidator voteValidator;
private final VoteStatusReader voteStatusReader;
private final VoteResultReader voteResultReader;
private final VoteWriter voteWriter;

@Transactional
Expand All @@ -40,12 +40,12 @@ public List<Long> vote(Long voterId, Long postId, List<Long> pollChoiceIds) {
return voteIds;
}

public List<VoteStatusResponse> findVoteStatus(Long userId, Long postId) {
public List<VoteResultResponse> findVoteResult(Long userId, Long postId) {
Post post = postRepository.findByIdFetchPollChoices(postId)
.orElseThrow(() -> new BadRequestException(ErrorCode.POST_NOT_FOUND));
List<Vote> totalVoteList = voteRepository.findAllByPostId(postId);
voteValidator.validateVoteStatusAccess(userId, post, totalVoteList);
voteValidator.validateVoteResultAccess(userId, post, totalVoteList);

return voteStatusReader.getVoteStatus(totalVoteList, post);
return voteResultReader.getVoteResult(totalVoteList, post);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private void validatePollChoiceId(Post post, List<Long> pollChoiceIds) {
}
}

public void validateVoteStatusAccess(Long userId, Post post, List<Vote> totalVoteList) {
public void validateVoteResultAccess(Long userId, Post post, List<Vote> totalVoteList) {
if (post.isClosed()) {
return;
}
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/com/chooz/vote/presentation/VoteController.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package com.chooz.vote.presentation;

import com.chooz.auth.domain.UserInfo;
import com.chooz.vote.presentation.dto.VoteStatusResponse;
import com.chooz.vote.presentation.dto.VoteResultResponse;
import com.chooz.vote.application.VoteService;
import com.chooz.vote.presentation.dto.VoteRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -32,11 +31,11 @@ public ResponseEntity<Void> vote(
return ResponseEntity.ok().build();
}

@GetMapping("/posts/{postId}/votes/status")
public ResponseEntity<List<VoteStatusResponse>> findVoteStatus(
@GetMapping("/posts/{postId}/votes/result")
public ResponseEntity<List<VoteResultResponse>> findVoteResult(
@PathVariable("postId") Long postId,
@AuthenticationPrincipal UserInfo userInfo
) {
return ResponseEntity.ok(voteService.findVoteStatus(userInfo.userId(), postId));
return ResponseEntity.ok(voteService.findVoteResult(userInfo.userId(), postId));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.chooz.vote.presentation.dto;

public record VoteStatusResponse(
public record VoteResultResponse(
Long id,
String title,
String imageUrl,
Expand Down
16 changes: 5 additions & 11 deletions src/test/java/com/chooz/vote/application/VoteServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,13 @@
import com.chooz.user.domain.UserRepository;
import com.chooz.vote.domain.Vote;
import com.chooz.vote.domain.VoteRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;

import java.time.Clock;
import java.time.LocalDateTime;
import java.util.List;

import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.*;
Expand Down Expand Up @@ -293,15 +287,15 @@ void multipleVote_cancelAllChoices() {

@Test
@DisplayName("투표 현황 조회")
void findVoteStatus() {
void findVoteResult() {
//given
User user = userRepository.save(UserFixture.createDefaultUser());
Post post = postRepository.save(PostFixture.createDefaultPost(user.getId()));
int voteIndex = 1;
voteRepository.save(VoteFixture.createDefaultVote(user.getId(), post.getId(), post.getPollChoices().get(voteIndex).getId()));

//when
var response = voteService.findVoteStatus(user.getId(), post.getId());
var response = voteService.findVoteResult(user.getId(), post.getId());

//then
assertAll(
Expand All @@ -328,21 +322,21 @@ void findVoteStatus_voteUser() {
voteRepository.save(VoteFixture.createDefaultVote(voter.getId(), post.getId(), post.getPollChoices().getFirst().getId()));

//when
var response = voteService.findVoteStatus(voter.getId(), post.getId());
var response = voteService.findVoteResult(voter.getId(), post.getId());

//then
assertThat(response).isNotNull();
}

@Test
@DisplayName("투표 현황 조회 - 작성자 아니고 투표 안 한 사람인 경우")
void findVoteStatus_notAuthorAndVoter() {
void findVoteResult_notAuthorAndVoter() {
//given
User user = userRepository.save(UserFixture.createDefaultUser());
Post post = postRepository.save(PostFixture.createDefaultPost(user.getId()));

//when
assertThatThrownBy(() -> voteService.findVoteStatus(2L, post.getId()))
assertThatThrownBy(() -> voteService.findVoteResult(2L, post.getId()))
.isInstanceOf(BadRequestException.class)
.hasMessage(ErrorCode.ACCESS_DENIED_VOTE_STATUS.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,14 @@ void validatePollChoiceId_invalidChoiceId() {

@Test
@DisplayName("validateVoteStatusAccess - 작성자가 아니고 투표하지 않은 사용자는 투표 현황 조회 불가")
void validateVoteStatusAccess_notAuthorAndNotVoter() {
void validateVoteResultAccess_notAuthorAndNotVoter() {
// given
Long userId = 999L;
Post post = PostFixture.createDefaultPost(1L); // 작성자 ID: 1L
List<Vote> votes = new ArrayList<>();

// when & then
assertThatThrownBy(() -> voteValidator.validateVoteStatusAccess(userId, post, votes))
assertThatThrownBy(() -> voteValidator.validateVoteResultAccess(userId, post, votes))
.isInstanceOf(BadRequestException.class)
.hasMessage(ErrorCode.ACCESS_DENIED_VOTE_STATUS.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.chooz.vote.presentation;

import com.chooz.vote.presentation.dto.VoteStatusResponse;
import com.chooz.vote.presentation.dto.VoteResultResponse;
import com.chooz.support.RestDocsTest;
import com.chooz.support.WithMockUserInfo;
import com.chooz.vote.presentation.dto.VoteRequest;
Expand Down Expand Up @@ -61,17 +61,17 @@ void vote() throws Exception {
@Test
@WithMockUserInfo
@DisplayName("게시글 투표 상태 조회")
void findVoteStatus() throws Exception {
void findVoteResult() throws Exception {
//given
var response = List.of(
new VoteStatusResponse(1L, "title1", "http://example.com/image/1", 2, "66.7"),
new VoteStatusResponse(2L, "title2", "http://example.com/image/2", 1, "33.3")
new VoteResultResponse(1L, "title1", "http://example.com/image/1", 2, "66.7"),
new VoteResultResponse(2L, "title2", "http://example.com/image/2", 1, "33.3")
);
given(voteService.findVoteStatus(1L, 1L))
given(voteService.findVoteResult(1L, 1L))
.willReturn(response);

//when then
mockMvc.perform(RestDocumentationRequestBuilders.get("/posts/{postId}/votes/status", 1)
mockMvc.perform(RestDocumentationRequestBuilders.get("/posts/{postId}/votes/result", 1)
.header(HttpHeaders.AUTHORIZATION, "Bearer token"))
.andExpect(status().isOk())
.andExpect(content().json(objectMapper.writeValueAsString(response)))
Expand Down