diff --git a/src/docs/asciidoc/posts.adoc b/src/docs/asciidoc/posts.adoc index 79fb7951..55a433b8 100644 --- a/src/docs/asciidoc/posts.adoc +++ b/src/docs/asciidoc/posts.adoc @@ -7,10 +7,17 @@ operation::post-controller-test/create-post[snippets='http-request,curl-request,request-headers,request-fields,http-response'] [[게시글-상세-조회]] -=== 게시글 상세 조회 (미구현) +=== `GET` 게시글 상세 조회 operation::post-controller-test/find-post[snippets='http-request,curl-request,path-parameters,http-response,response-fields'] +[[사진-투표-현황-조회]] +=== `GET` 사진 투표 현황 조회 + +operation::post-controller-test/find-vote-status[snippets='http-request,curl-request,request-headers,path-parameters,http-response,response-fields'] + +[[게시글-목록-조회]] + [[내가-작성한-게시글-조회]] === `GET` 내가 작성한 게시글 조회 diff --git a/src/main/java/com/swyp8team2/common/presentation/HttpLoggingFilter.java b/src/main/java/com/swyp8team2/common/presentation/HttpLoggingFilter.java index 45d48741..8d235e3a 100644 --- a/src/main/java/com/swyp8team2/common/presentation/HttpLoggingFilter.java +++ b/src/main/java/com/swyp8team2/common/presentation/HttpLoggingFilter.java @@ -34,7 +34,7 @@ public class HttpLoggingFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { - if (request.getRequestURI().startsWith("/docs")) { + if (request.getRequestURI().startsWith("/docs") || request.getRequestURI().startsWith("/h2-console")) { chain.doFilter(request, response); return; } diff --git a/src/main/java/com/swyp8team2/post/application/PostService.java b/src/main/java/com/swyp8team2/post/application/PostService.java index 79a19f8e..1eb11b6f 100644 --- a/src/main/java/com/swyp8team2/post/application/PostService.java +++ b/src/main/java/com/swyp8team2/post/application/PostService.java @@ -11,20 +11,21 @@ import com.swyp8team2.post.domain.PostRepository; import com.swyp8team2.post.presentation.dto.CreatePostRequest; import com.swyp8team2.post.presentation.dto.PostResponse; +import com.swyp8team2.post.presentation.dto.PostImageVoteStatusResponse; import com.swyp8team2.post.presentation.dto.SimplePostResponse; -import com.swyp8team2.post.presentation.dto.VoteResponseDto; +import com.swyp8team2.post.presentation.dto.PostImageResponse; import com.swyp8team2.user.domain.User; import com.swyp8team2.user.domain.UserRepository; import com.swyp8team2.vote.domain.Vote; import com.swyp8team2.vote.domain.VoteRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Objects; @Service @Transactional(readOnly = true) @@ -47,43 +48,47 @@ public Long create(Long userId, CreatePostRequest request) { private List createPostImages(CreatePostRequest request) { PostImageNameGenerator nameGenerator = new PostImageNameGenerator(); - return request.votes().stream() + return request.images().stream() .map(voteRequestDto -> PostImage.create( nameGenerator.generate(), voteRequestDto.imageFileId() )).toList(); } - public PostResponse findById(Long postId) { + public PostResponse findById(Long userId, Long postId) { Post post = postRepository.findById(postId) .orElseThrow(() -> new BadRequestException(ErrorCode.POST_NOT_FOUND)); - User user = userRepository.findById(post.getUserId()) + User author = userRepository.findById(post.getUserId()) .orElseThrow(() -> new BadRequestException(ErrorCode.USER_NOT_FOUND)); + List votes = createPostImageResponse(userId, postId, post); + return PostResponse.of(post, author, votes); + } + + private List createPostImageResponse(Long userId, Long postId, Post post) { List images = post.getImages(); - List votes = images.stream() - .map(image -> createVoteResponseDto(image, images)) + return images.stream() + .map(image -> createVoteResponseDto(image, userId, postId)) .toList(); - return PostResponse.of(post, user, votes); } - private VoteResponseDto createVoteResponseDto(PostImage image, List images) { + private PostImageResponse createVoteResponseDto(PostImage image, Long userId, Long postId) { ImageFile imageFile = imageFileRepository.findById(image.getImageFileId()) .orElseThrow(() -> new InternalServerException(ErrorCode.IMAGE_FILE_NOT_FOUND)); - return new VoteResponseDto( + boolean voted = Objects.nonNull(userId) && getVoted(image, userId, postId); + return new PostImageResponse( image.getId(), + image.getName(), imageFile.getImageUrl(), - image.getVoteCount(), - ratioCalculator.calculateRatio(getTotalVoteCount(images), image.getVoteCount()), - false //TODO: implement + voted ); } - private int getTotalVoteCount(List images) { - int totalVoteCount = 0; - for (PostImage image : images) { - totalVoteCount += image.getVoteCount(); - } - return totalVoteCount; + private Boolean getVoted(PostImage image, Long userId, Long postId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new BadRequestException(ErrorCode.USER_NOT_FOUND)); + return voteRepository.findByUserSeqAndPostId(user.getSeq(), postId) + .map(vote -> vote.getPostImageId().equals(image.getId())) + .orElse(false); } public CursorBasePaginatedResponse findMyPosts(Long userId, Long cursor, int size) { @@ -107,4 +112,23 @@ public CursorBasePaginatedResponse findVotedPosts(Long userI Slice postSlice = postRepository.findByIdIn(postIds, cursor, PageRequest.ofSize(size)); return CursorBasePaginatedResponse.of(postSlice.map(this::createSimplePostResponse)); } + + public List findPostStatus(Long postId) { + Post post = postRepository.findById(postId) + .orElseThrow(() -> new BadRequestException(ErrorCode.POST_NOT_FOUND)); + int totalVoteCount = getTotalVoteCount(post.getImages()); + return post.getImages().stream() + .map(image -> { + String ratio = ratioCalculator.calculate(image.getVoteCount(), totalVoteCount); + return new PostImageVoteStatusResponse(image.getName(), image.getVoteCount(), ratio); + }).toList(); + } + + private int getTotalVoteCount(List images) { + int totalVoteCount = 0; + for (PostImage image : images) { + totalVoteCount += image.getVoteCount(); + } + return totalVoteCount; + } } diff --git a/src/main/java/com/swyp8team2/post/application/RatioCalculator.java b/src/main/java/com/swyp8team2/post/application/RatioCalculator.java index 39e94ef9..1f4c8ec1 100644 --- a/src/main/java/com/swyp8team2/post/application/RatioCalculator.java +++ b/src/main/java/com/swyp8team2/post/application/RatioCalculator.java @@ -8,7 +8,7 @@ @Component public class RatioCalculator { - public String calculateRatio(int totalVoteCount, int voteCount) { + public String calculate(int totalVoteCount, int voteCount) { if (totalVoteCount == 0) { return "0.0"; } diff --git a/src/main/java/com/swyp8team2/post/domain/Post.java b/src/main/java/com/swyp8team2/post/domain/Post.java index f799e21a..b036b0e8 100644 --- a/src/main/java/com/swyp8team2/post/domain/Post.java +++ b/src/main/java/com/swyp8team2/post/domain/Post.java @@ -83,7 +83,7 @@ public void vote(Long imageId) { PostImage image = images.stream() .filter(postImage -> postImage.getId().equals(imageId)) .findFirst() - .orElseThrow(() -> new InternalServerException(ErrorCode.POST_IMAGE_NOT_FOUND)); + .orElseThrow(() -> new BadRequestException(ErrorCode.POST_IMAGE_NOT_FOUND)); image.increaseVoteCount(); } diff --git a/src/main/java/com/swyp8team2/post/presentation/PostController.java b/src/main/java/com/swyp8team2/post/presentation/PostController.java index 62489ca2..1d67011e 100644 --- a/src/main/java/com/swyp8team2/post/presentation/PostController.java +++ b/src/main/java/com/swyp8team2/post/presentation/PostController.java @@ -5,9 +5,10 @@ import com.swyp8team2.post.application.PostService; import com.swyp8team2.post.presentation.dto.AuthorDto; import com.swyp8team2.post.presentation.dto.CreatePostRequest; +import com.swyp8team2.post.presentation.dto.PostImageVoteStatusResponse; import com.swyp8team2.post.presentation.dto.PostResponse; import com.swyp8team2.post.presentation.dto.SimplePostResponse; -import com.swyp8team2.post.presentation.dto.VoteResponseDto; +import com.swyp8team2.post.presentation.dto.PostImageResponse; import jakarta.validation.Valid; import jakarta.validation.constraints.Min; import lombok.RequiredArgsConstructor; @@ -24,6 +25,7 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; @RestController @RequiredArgsConstructor @@ -41,7 +43,25 @@ public ResponseEntity createPost( return ResponseEntity.ok().build(); } - @GetMapping("/{shareUrl}") + @GetMapping("/{postId}") + public ResponseEntity findPost( + @PathVariable("postId") Long postId, + @AuthenticationPrincipal UserInfo userInfo + ) { + Long userId = Optional.ofNullable(userInfo) + .map(UserInfo::userId) + .orElse(null); + return ResponseEntity.ok(postService.findById(userId, postId)); + } + + @GetMapping("/{postId}/status") + public ResponseEntity> findVoteStatus( + @PathVariable("postId") Long postId + ) { + return ResponseEntity.ok(postService.findPostStatus(postId)); + } + +// @GetMapping("/{shareUrl}") public ResponseEntity findPost(@PathVariable("shareUrl") String shareUrl) { return ResponseEntity.ok(new PostResponse( 1L, @@ -52,8 +72,8 @@ public ResponseEntity findPost(@PathVariable("shareUrl") String sh ), "description", List.of( - new VoteResponseDto(1L, "https://image.photopic.site/1", 3, "60.0", true), - new VoteResponseDto(2L, "https://image.photopic.site/2", 2, "40.0", false) + new PostImageResponse(1L, "뽀또A", "https://image.photopic.site/1", true), + new PostImageResponse(2L, "뽀또B", "https://image.photopic.site/2", false) ), "https://photopic.site/shareurl", LocalDateTime.of(2025, 2, 13, 12, 0) diff --git a/src/main/java/com/swyp8team2/post/presentation/dto/CreatePostRequest.java b/src/main/java/com/swyp8team2/post/presentation/dto/CreatePostRequest.java index 6d3f326c..1efb3b7a 100644 --- a/src/main/java/com/swyp8team2/post/presentation/dto/CreatePostRequest.java +++ b/src/main/java/com/swyp8team2/post/presentation/dto/CreatePostRequest.java @@ -2,7 +2,6 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; import java.util.List; @@ -11,6 +10,6 @@ public record CreatePostRequest( String description, @Valid @NotNull - List votes + List images ) { } diff --git a/src/main/java/com/swyp8team2/post/presentation/dto/VoteRequestDto.java b/src/main/java/com/swyp8team2/post/presentation/dto/PostImageRequestDto.java similarity index 80% rename from src/main/java/com/swyp8team2/post/presentation/dto/VoteRequestDto.java rename to src/main/java/com/swyp8team2/post/presentation/dto/PostImageRequestDto.java index d532cdda..15aeeeef 100644 --- a/src/main/java/com/swyp8team2/post/presentation/dto/VoteRequestDto.java +++ b/src/main/java/com/swyp8team2/post/presentation/dto/PostImageRequestDto.java @@ -2,7 +2,7 @@ import jakarta.validation.constraints.NotNull; -public record VoteRequestDto( +public record PostImageRequestDto( @NotNull Long imageFileId ) { diff --git a/src/main/java/com/swyp8team2/post/presentation/dto/VoteResponseDto.java b/src/main/java/com/swyp8team2/post/presentation/dto/PostImageResponse.java similarity index 59% rename from src/main/java/com/swyp8team2/post/presentation/dto/VoteResponseDto.java rename to src/main/java/com/swyp8team2/post/presentation/dto/PostImageResponse.java index 9c3bffcf..28b3280c 100644 --- a/src/main/java/com/swyp8team2/post/presentation/dto/VoteResponseDto.java +++ b/src/main/java/com/swyp8team2/post/presentation/dto/PostImageResponse.java @@ -1,10 +1,9 @@ package com.swyp8team2.post.presentation.dto; -public record VoteResponseDto( +public record PostImageResponse( Long id, + String imageName, String imageUrl, - int voteCount, - String voteRatio, boolean voted ) { } diff --git a/src/main/java/com/swyp8team2/post/presentation/dto/PostImageVoteStatusResponse.java b/src/main/java/com/swyp8team2/post/presentation/dto/PostImageVoteStatusResponse.java new file mode 100644 index 00000000..652f0899 --- /dev/null +++ b/src/main/java/com/swyp8team2/post/presentation/dto/PostImageVoteStatusResponse.java @@ -0,0 +1,8 @@ +package com.swyp8team2.post.presentation.dto; + +public record PostImageVoteStatusResponse( + String imageName, + int voteCount, + String voteRatio +) { +} diff --git a/src/main/java/com/swyp8team2/post/presentation/dto/PostResponse.java b/src/main/java/com/swyp8team2/post/presentation/dto/PostResponse.java index cd0849ae..cb32afc3 100644 --- a/src/main/java/com/swyp8team2/post/presentation/dto/PostResponse.java +++ b/src/main/java/com/swyp8team2/post/presentation/dto/PostResponse.java @@ -10,16 +10,16 @@ public record PostResponse( Long id, AuthorDto author, String description, - List votes, + List images, String shareUrl, LocalDateTime createdAt ) { - public static PostResponse of(Post post, User user, List votes) { + public static PostResponse of(Post post, User user, List images) { return new PostResponse( post.getId(), AuthorDto.of(user), post.getDescription(), - votes, + images, post.getShareUrl(), post.getCreatedAt() ); diff --git a/src/test/java/com/swyp8team2/post/application/PostServiceTest.java b/src/test/java/com/swyp8team2/post/application/PostServiceTest.java index 85f831f1..6921d19a 100644 --- a/src/test/java/com/swyp8team2/post/application/PostServiceTest.java +++ b/src/test/java/com/swyp8team2/post/application/PostServiceTest.java @@ -4,18 +4,17 @@ import com.swyp8team2.common.exception.ErrorCode; import com.swyp8team2.image.domain.ImageFile; import com.swyp8team2.image.domain.ImageFileRepository; -import com.swyp8team2.image.presentation.dto.ImageFileDto; import com.swyp8team2.post.domain.Post; import com.swyp8team2.post.domain.PostImage; import com.swyp8team2.post.domain.PostRepository; import com.swyp8team2.post.presentation.dto.CreatePostRequest; import com.swyp8team2.post.presentation.dto.PostResponse; -import com.swyp8team2.post.presentation.dto.SimplePostResponse; -import com.swyp8team2.post.presentation.dto.VoteRequestDto; -import com.swyp8team2.post.presentation.dto.VoteResponseDto; +import com.swyp8team2.post.presentation.dto.PostImageRequestDto; +import com.swyp8team2.post.presentation.dto.PostImageResponse; import com.swyp8team2.support.IntegrationTest; import com.swyp8team2.user.domain.User; import com.swyp8team2.user.domain.UserRepository; +import com.swyp8team2.vote.application.VoteService; import com.swyp8team2.vote.domain.Vote; import com.swyp8team2.vote.domain.VoteRepository; import org.junit.jupiter.api.DisplayName; @@ -49,14 +48,17 @@ class PostServiceTest extends IntegrationTest { @Autowired VoteRepository voteRepository; + @Autowired + VoteService voteService; + @Test @DisplayName("게시글 작성") void create() throws Exception { //given long userId = 1L; CreatePostRequest request = new CreatePostRequest("description", List.of( - new VoteRequestDto(1L), - new VoteRequestDto(2L) + new PostImageRequestDto(1L), + new PostImageRequestDto(2L) )); //when @@ -84,7 +86,7 @@ void create_invalidPostImageCount() throws Exception { //given long userId = 1L; CreatePostRequest request = new CreatePostRequest("description", List.of( - new VoteRequestDto(1L) + new PostImageRequestDto(1L) )); //when then @@ -99,8 +101,8 @@ void create_descriptionCountExceeded() throws Exception { //given long userId = 1L; CreatePostRequest request = new CreatePostRequest("a".repeat(101), List.of( - new VoteRequestDto(1L), - new VoteRequestDto(2L) + new PostImageRequestDto(1L), + new PostImageRequestDto(2L) )); //when then @@ -119,10 +121,10 @@ void findById() throws Exception { Post post = postRepository.save(createPost(user.getId(), imageFile1, imageFile2, 1)); //when - PostResponse response = postService.findById(post.getId()); + PostResponse response = postService.findById(user.getId(), post.getId()); //then - List votes = response.votes(); + List votes = response.images(); assertAll( () -> assertThat(response.description()).isEqualTo(post.getDescription()), () -> assertThat(response.id()).isEqualTo(post.getId()), @@ -131,12 +133,8 @@ void findById() throws Exception { () -> assertThat(response.shareUrl()).isEqualTo(post.getShareUrl()), () -> assertThat(votes).hasSize(2), () -> assertThat(votes.get(0).imageUrl()).isEqualTo(imageFile1.getImageUrl()), - () -> assertThat(votes.get(0).voteCount()).isEqualTo(0), - () -> assertThat(votes.get(0).voteRatio()).isEqualTo("0.0"), () -> assertThat(votes.get(0).voted()).isFalse(), () -> assertThat(votes.get(1).imageUrl()).isEqualTo(imageFile2.getImageUrl()), - () -> assertThat(votes.get(1).voteCount()).isEqualTo(0), - () -> assertThat(votes.get(1).voteRatio()).isEqualTo("0.0"), () -> assertThat(votes.get(1).voted()).isFalse() ); } @@ -212,4 +210,29 @@ void findVotedPosts() throws Exception { () -> assertThat(response.nextCursor()).isEqualTo(posts.get(전체_15개에서_맨_마지막_데이터_인덱스).getId()) ); } + + @Test + @DisplayName("투표 현황 조회") + void findPostStatus() throws Exception { + //given + User user = userRepository.save(createUser(1)); + ImageFile imageFile1 = imageFileRepository.save(createImageFile(1)); + ImageFile imageFile2 = imageFileRepository.save(createImageFile(2)); + Post post = postRepository.save(createPost(user.getId(), imageFile1, imageFile2, 1)); + voteService.vote(user.getId(), post.getId(), post.getImages().get(0).getId()); + + //when + var response = postService.findPostStatus(post.getId()); + + //then + assertAll( + () -> assertThat(response).hasSize(2), + () -> assertThat(response.get(0).imageName()).isEqualTo(post.getImages().get(0).getName()), + () -> assertThat(response.get(0).voteCount()).isEqualTo(1), + () -> assertThat(response.get(0).voteRatio()).isEqualTo("100.0"), + () -> assertThat(response.get(1).imageName()).isEqualTo(post.getImages().get(1).getName()), + () -> assertThat(response.get(1).voteCount()).isEqualTo(0), + () -> assertThat(response.get(1).voteRatio()).isEqualTo("0.0") + ); + } } diff --git a/src/test/java/com/swyp8team2/post/application/RatioCalculatorTest.java b/src/test/java/com/swyp8team2/post/application/RatioCalculatorTest.java index e0cf8b8d..c9262704 100644 --- a/src/test/java/com/swyp8team2/post/application/RatioCalculatorTest.java +++ b/src/test/java/com/swyp8team2/post/application/RatioCalculatorTest.java @@ -2,12 +2,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; class RatioCalculatorTest { @@ -25,7 +23,7 @@ void calculate(int totalVoteCount, int voteCount, String result) throws Exceptio //given //when - String ratio = ratioCalculator.calculateRatio(totalVoteCount, voteCount); + String ratio = ratioCalculator.calculate(totalVoteCount, voteCount); //then assertThat(ratio).isEqualTo(result); diff --git a/src/test/java/com/swyp8team2/post/presentation/PostControllerTest.java b/src/test/java/com/swyp8team2/post/presentation/PostControllerTest.java index cca74096..809dc400 100644 --- a/src/test/java/com/swyp8team2/post/presentation/PostControllerTest.java +++ b/src/test/java/com/swyp8team2/post/presentation/PostControllerTest.java @@ -3,10 +3,11 @@ import com.swyp8team2.common.dto.CursorBasePaginatedResponse; import com.swyp8team2.post.presentation.dto.AuthorDto; import com.swyp8team2.post.presentation.dto.CreatePostRequest; +import com.swyp8team2.post.presentation.dto.PostImageVoteStatusResponse; import com.swyp8team2.post.presentation.dto.PostResponse; import com.swyp8team2.post.presentation.dto.SimplePostResponse; -import com.swyp8team2.post.presentation.dto.VoteRequestDto; -import com.swyp8team2.post.presentation.dto.VoteResponseDto; +import com.swyp8team2.post.presentation.dto.PostImageRequestDto; +import com.swyp8team2.post.presentation.dto.PostImageResponse; import com.swyp8team2.support.RestDocsTest; import com.swyp8team2.support.WithMockUserInfo; import org.junit.jupiter.api.DisplayName; @@ -20,6 +21,7 @@ import java.time.LocalDateTime; import java.util.List; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; @@ -42,7 +44,7 @@ void createPost() throws Exception { //given CreatePostRequest request = new CreatePostRequest( "제목", - List.of(new VoteRequestDto(1L), new VoteRequestDto(2L)) + List.of(new PostImageRequestDto(1L), new PostImageRequestDto(2L)) ); //when then @@ -58,11 +60,11 @@ void createPost() throws Exception { .type(JsonFieldType.STRING) .description("설명") .attributes(constraints("0~100자 사이")), - fieldWithPath("votes") + fieldWithPath("images") .type(JsonFieldType.ARRAY) .description("투표 후보") .attributes(constraints("최소 2개")), - fieldWithPath("votes[].imageFileId") + fieldWithPath("images[].imageFileId") .type(JsonFieldType.NUMBER) .description("투표 후보 이미지 ID") ))); @@ -82,20 +84,22 @@ void findPost() throws Exception { ), "description", List.of( - new VoteResponseDto(1L, "https://image.photopic.site/1", 3, "60.0", true), - new VoteResponseDto(2L, "https://image.photopic.site/2", 2, "40.0", false) + new PostImageResponse(1L, "뽀또A", "https://image.photopic.site/1", true), + new PostImageResponse(2L, "뽀또B", "https://image.photopic.site/2", false) ), "https://photopic.site/shareurl", LocalDateTime.of(2025, 2, 13, 12, 0) ); + given(postService.findById(any(), any())) + .willReturn(response); //when then - mockMvc.perform(RestDocumentationRequestBuilders.get("/posts/{shareUrl}", "shareUrl")) + mockMvc.perform(RestDocumentationRequestBuilders.get("/posts/{postId}", 1)) .andExpect(status().isOk()) .andExpect(content().json(objectMapper.writeValueAsString(response))) .andDo(restDocs.document( pathParameters( - parameterWithName("shareUrl").description("게시글 공유 URL") + parameterWithName("postId").description("게시글 Id") ), responseFields( fieldWithPath("id").type(JsonFieldType.NUMBER).description("게시글 Id"), @@ -104,18 +108,48 @@ void findPost() throws Exception { fieldWithPath("author.nickname").type(JsonFieldType.STRING).description("게시글 작성자 닉네임"), fieldWithPath("author.profileUrl").type(JsonFieldType.STRING).description("게시글 작성자 프로필 이미지"), fieldWithPath("description").type(JsonFieldType.STRING).description("설명"), - fieldWithPath("votes[]").type(JsonFieldType.ARRAY).description("투표 선택지 목록"), - fieldWithPath("votes[].id").type(JsonFieldType.NUMBER).description("투표 선택지 Id"), - fieldWithPath("votes[].imageUrl").type(JsonFieldType.STRING).description("투표 이미지"), - fieldWithPath("votes[].voteRatio").type(JsonFieldType.STRING).description("득표 비율"), - fieldWithPath("votes[].voteCount").type(JsonFieldType.NUMBER).description("득표 수"), - fieldWithPath("votes[].voted").type(JsonFieldType.BOOLEAN).description("투표 여부"), + fieldWithPath("images[]").type(JsonFieldType.ARRAY).description("투표 선택지 목록"), + fieldWithPath("images[].id").type(JsonFieldType.NUMBER).description("투표 선택지 Id"), + fieldWithPath("images[].imageName").type(JsonFieldType.STRING).description("사진 이름"), + fieldWithPath("images[].imageUrl").type(JsonFieldType.STRING).description("사진 이미지"), + fieldWithPath("images[].voted").type(JsonFieldType.BOOLEAN).description("투표 여부"), fieldWithPath("shareUrl").type(JsonFieldType.STRING).description("게시글 공유 URL"), fieldWithPath("createdAt").type(JsonFieldType.STRING).description("게시글 생성 시간") ) )); } + @Test + @WithMockUserInfo + @DisplayName("게시글 투표 상태 조회") + void findVoteStatus() throws Exception { + //given + var response = List.of( + new PostImageVoteStatusResponse("뽀또A", 2, "66.7"), + new PostImageVoteStatusResponse("뽀또B", 1, "33.3") + ); + given(postService.findPostStatus(1L)) + .willReturn(response); + + //when then + mockMvc.perform(RestDocumentationRequestBuilders.get("/posts/{postId}/status", 1) + .header(HttpHeaders.AUTHORIZATION, "Bearer token")) + .andExpect(status().isOk()) + .andExpect(content().json(objectMapper.writeValueAsString(response))) + .andDo(restDocs.document( + requestHeaders(authorizationHeader()), + pathParameters( + parameterWithName("postId").description("게시글 Id") + ), + responseFields( + fieldWithPath("[]").type(JsonFieldType.ARRAY).description("투표 선택지 목록"), + fieldWithPath("[].imageName").type(JsonFieldType.STRING).description("사진 이름"), + fieldWithPath("[].voteCount").type(JsonFieldType.NUMBER).description("투표 수"), + fieldWithPath("[].voteRatio").type(JsonFieldType.STRING).description("투표 비율") + ) + )); + } + @Test @WithMockUserInfo @DisplayName("게시글 삭제")