diff --git a/src/main/java/com/devin/dev/SampleData.java b/src/main/java/com/devin/dev/SampleData.java index cc525d6..5f00841 100644 --- a/src/main/java/com/devin/dev/SampleData.java +++ b/src/main/java/com/devin/dev/SampleData.java @@ -60,7 +60,7 @@ public void createReplies() { for (UserDetailsDto userDto : userDtos) { for (PostDetailsDto postDto : postDtos) { for (int i = 0; i < 2; i++) { - DefaultResponse response = replyService.reply(userDto.getId(), postDto.getPostId(), + DefaultResponse response = replyService.reply(userDto.getId(), postDto.getPost_id(), "reply_content_" + i, List.of("reply_img_1", "reply_img_2", "reply_img_3")); replyDtos.add(response.getData()); diff --git a/src/main/java/com/devin/dev/controller/post/PostController.java b/src/main/java/com/devin/dev/controller/post/PostController.java index df76aa0..df9a272 100644 --- a/src/main/java/com/devin/dev/controller/post/PostController.java +++ b/src/main/java/com/devin/dev/controller/post/PostController.java @@ -1,15 +1,18 @@ package com.devin.dev.controller.post; +import com.devin.dev.controller.reply.ReplyOrderCondition; +import com.devin.dev.dto.post.PostDetailsDto; import com.devin.dev.model.DefaultResponse; +import com.devin.dev.security.JwtAuthTokenProvider; import com.devin.dev.service.PostService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletRequest; + @RestController @RequiredArgsConstructor public class PostController { @@ -17,9 +20,38 @@ public class PostController { private final PostService postService; @GetMapping("/postlist/posts") - public DefaultResponse getPostList(@RequestParam(defaultValue = "-1")Long id, - @PageableDefault(page = 0, sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable) { + public DefaultResponse getPostList(@RequestParam(defaultValue = "-1") Long id, + @PageableDefault(page = 0, sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable) { return postService.getPostInfoList(id, pageable); } + @GetMapping("/postlist/{id}") + public DefaultResponse getPostDetails( + @PathVariable("id") Long postId, + @RequestParam(defaultValue = "true", name = "sort_reply") boolean sort_reply) { + ReplyOrderCondition replyOrderCondition = new ReplyOrderCondition(); + if (!sort_reply) { + replyOrderCondition.setLatestDate(true); + } else { + replyOrderCondition.setLikeCount(true); + } + return postService.getPost(postId, replyOrderCondition); + } + + @GetMapping("/postlist") + public DefaultResponse getPostListByCondition( + PostSearchCondition condition, + @PageableDefault(page = 0, sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable) { + return postService.getPostInfoListByCondition(condition, pageable); + } + + @DeleteMapping("/post/{id}") + public DefaultResponse deletePost(@PathVariable("id") Long postId) { + return postService.deletePost(postId); + } + + @PostMapping("/post") + public DefaultResponse post(@RequestBody PostForm form, HttpServletRequest request) { + return postService.post(request, form); + } } diff --git a/src/main/java/com/devin/dev/controller/post/PostForm.java b/src/main/java/com/devin/dev/controller/post/PostForm.java new file mode 100644 index 0000000..811df9b --- /dev/null +++ b/src/main/java/com/devin/dev/controller/post/PostForm.java @@ -0,0 +1,13 @@ +package com.devin.dev.controller.post; + +import lombok.Data; + +import java.util.List; + +@Data +public class PostForm { + private String title; + private String content; + private List post_images; + private List post_tags; +} diff --git a/src/main/java/com/devin/dev/controller/reply/ReplyOrderCondition.java b/src/main/java/com/devin/dev/controller/reply/ReplyOrderCondition.java new file mode 100644 index 0000000..be36ced --- /dev/null +++ b/src/main/java/com/devin/dev/controller/reply/ReplyOrderCondition.java @@ -0,0 +1,9 @@ +package com.devin.dev.controller.reply; + +import lombok.Data; + +@Data +public class ReplyOrderCondition { + private boolean likeCount; + private boolean latestDate; +} diff --git a/src/main/java/com/devin/dev/dto/post/PostDetailsDto.java b/src/main/java/com/devin/dev/dto/post/PostDetailsDto.java index a27cbd2..31edc22 100644 --- a/src/main/java/com/devin/dev/dto/post/PostDetailsDto.java +++ b/src/main/java/com/devin/dev/dto/post/PostDetailsDto.java @@ -6,42 +6,61 @@ import com.querydsl.core.annotations.QueryProjection; import lombok.Data; -import java.util.ArrayList; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @Data public class PostDetailsDto { - private Long postId; - private Long userId; + private Long post_id; + private Long publisher_id; + private String publisher_name; + private String publisher_profile; + private Long publisher_exp; private String title; - private String username; private String content; - private PostStatus status; - private Integer replyQuantity; - private List imagePaths; + private List post_images; + private List post_tags; + private boolean status_accept; + private LocalDateTime date_create; + private LocalDateTime date_update; + private Integer reply_num; + private List reply; @QueryProjection - public PostDetailsDto(Long postId, Long userId, String title, String username, String content, PostStatus status, Integer replyQuantity, List imagePaths) { - this.postId = postId; - this.userId = userId; + public PostDetailsDto(Long post_id, Long publisher_id, String publisher_name, String publisher_profile, Long publisher_exp, String title, String content, List post_images, List post_tags, boolean status_accept, boolean like_post, LocalDateTime date_create, LocalDateTime date_update, Integer reply_num, List replyDtos) { + this.post_id = post_id; + this.publisher_id = publisher_id; + this.publisher_name = publisher_name; + this.publisher_profile = publisher_profile; + this.publisher_exp = publisher_exp; this.title = title; - this.username = username; this.content = content; - this.status = status; - this.replyQuantity = replyQuantity; - this.imagePaths = imagePaths; + this.post_images = post_images; + this.post_tags = post_tags; + this.status_accept = status_accept; + this.date_create = date_create; + this.date_update = date_update; + this.reply_num = reply_num; + this.reply = replyDtos; } public PostDetailsDto(Post post) { - this.postId = post.getId(); - this.userId = post.getUser().getId(); + this.post_id = post.getId(); + this.publisher_id = post.getUser().getId(); + this.publisher_name = post.getUser().getName(); + this.publisher_profile = post.getUser().getProfile(); + this.publisher_exp = post.getUser().getExp(); this.title = post.getTitle(); - this.username = post.getUser().getName(); this.content = post.getContent(); - this.status = post.getStatus(); - this.replyQuantity = post.getReplies().size(); - this.imagePaths = post.getImages().stream().map(PostImage::getPath).collect(Collectors.toList()); + this.post_images = post.getImages().stream().map(PostImage::getPath).collect(Collectors.toList()); + this.post_tags = post.getPostTags(); + this.status_accept = post.getStatus() == PostStatus.SELECTED; + this.date_create = post.getCreatedDate(); + this.date_update = post.getLastModifiedDate(); + this.reply_num = post.getReplies().size(); + this.reply = post.getReplies().stream().map(PostReplyDto::new).collect(Collectors.toList()); } } diff --git a/src/main/java/com/devin/dev/dto/post/PostReplyDto.java b/src/main/java/com/devin/dev/dto/post/PostReplyDto.java index a617cd1..5061d68 100644 --- a/src/main/java/com/devin/dev/dto/post/PostReplyDto.java +++ b/src/main/java/com/devin/dev/dto/post/PostReplyDto.java @@ -1,25 +1,56 @@ package com.devin.dev.dto.post; +import com.devin.dev.entity.reply.Reply; +import com.devin.dev.entity.reply.ReplyImage; +import com.devin.dev.entity.reply.ReplyStatus; import com.querydsl.core.annotations.QueryProjection; import lombok.Data; +import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; @Data public class PostReplyDto { - private Long postId; - private Long userId; - private String username; + private Long reply_id; + private Long publisher_id; + private String publisher_name; + private String publisher_profile; + private Long publisher_exp; private String content; - private List imagePaths; + private List reply_images; + private boolean status_accept; + private Integer like_num; + private LocalDateTime date_create; + private LocalDateTime date_update; @QueryProjection - public PostReplyDto(Long postId, Long userId, String username, String content, List imagePaths) { - this.postId = postId; - this.userId = userId; - this.username = username; + public PostReplyDto(Long reply_id, Long publisher_id, String publisher_name, String publisher_profile, Long publisher_exp, String content, List reply_images, boolean status_accept, boolean like_reply, Integer like_num, LocalDateTime date_create, LocalDateTime date_update) { + this.reply_id = reply_id; + this.publisher_id = publisher_id; + this.publisher_name = publisher_name; + this.publisher_profile = publisher_profile; + this.publisher_exp = publisher_exp; this.content = content; - this.imagePaths = imagePaths; + this.reply_images = reply_images; + this.status_accept = status_accept; + this.like_num = like_num; + this.date_create = date_create; + this.date_update = date_update; + } + + public PostReplyDto(Reply reply) { + this.reply_id = reply.getId(); + this.publisher_id = reply.getUser().getId(); + this.publisher_name = reply.getUser().getName(); + this.publisher_profile = reply.getUser().getProfile(); + this.publisher_exp = reply.getUser().getExp(); + this.content = reply.getContent(); + this.reply_images = reply.getImages().stream().map(ReplyImage::getPath).collect(Collectors.toList()); + this.status_accept = ReplyStatus.SELECTED == reply.getStatus(); + this.like_num = reply.getLikes().size(); + this.date_create = reply.getCreatedDate(); + this.date_update = reply.getLastModifiedDate(); } } diff --git a/src/main/java/com/devin/dev/repository/post/PostLikeRepository.java b/src/main/java/com/devin/dev/repository/post/PostLikeRepository.java new file mode 100644 index 0000000..7d9fcf0 --- /dev/null +++ b/src/main/java/com/devin/dev/repository/post/PostLikeRepository.java @@ -0,0 +1,7 @@ +package com.devin.dev.repository.post; + +import com.devin.dev.entity.post.PostLike; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostLikeRepository extends JpaRepository { +} diff --git a/src/main/java/com/devin/dev/repository/post/PostRepositoryQuery.java b/src/main/java/com/devin/dev/repository/post/PostRepositoryQuery.java index f7ba19b..803e156 100644 --- a/src/main/java/com/devin/dev/repository/post/PostRepositoryQuery.java +++ b/src/main/java/com/devin/dev/repository/post/PostRepositoryQuery.java @@ -1,6 +1,9 @@ package com.devin.dev.repository.post; import com.devin.dev.controller.post.PostSearchCondition; +import com.devin.dev.controller.reply.ReplyOrderCondition; +import com.devin.dev.dto.post.PostDetailsDto; +import com.devin.dev.dto.post.PostInfoDto; import com.devin.dev.dto.post.PostSimpleDto; import com.devin.dev.entity.post.Post; import com.devin.dev.entity.user.User; @@ -8,14 +11,17 @@ import org.springframework.data.domain.Pageable; import java.util.List; +import java.util.Optional; public interface PostRepositoryQuery { Page findPostnamePageByUser(User user, Pageable pageable); - Page findPostDtoPageWithCondition(PostSearchCondition condition, Pageable pageable); + Page findPostInfoDtoPageByCondition(PostSearchCondition condition, Pageable pageable); List findPostDtoByUser(User user); Page findAllByTagId(Long id, Pageable pageable); + + Optional findPostDetailsById(Long id, ReplyOrderCondition condition); } diff --git a/src/main/java/com/devin/dev/repository/post/PostRepositoryQueryImpl.java b/src/main/java/com/devin/dev/repository/post/PostRepositoryQueryImpl.java index 40a2cd9..2027333 100644 --- a/src/main/java/com/devin/dev/repository/post/PostRepositoryQueryImpl.java +++ b/src/main/java/com/devin/dev/repository/post/PostRepositoryQueryImpl.java @@ -1,11 +1,15 @@ package com.devin.dev.repository.post; import com.devin.dev.controller.post.PostSearchCondition; -import com.devin.dev.dto.post.PostSimpleDto; -import com.devin.dev.dto.post.QPostSimpleDto; +import com.devin.dev.controller.reply.ReplyOrderCondition; +import com.devin.dev.dto.post.*; import com.devin.dev.entity.post.*; +import com.devin.dev.entity.reply.QReply; +import com.devin.dev.entity.reply.QReplyImage; +import com.devin.dev.entity.reply.QReplyLike; import com.devin.dev.entity.user.User; import com.querydsl.core.QueryResults; +import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -16,10 +20,17 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; import static com.devin.dev.entity.post.QPost.post; +import static com.devin.dev.entity.post.QPostImage.postImage; +import static com.devin.dev.entity.post.QPostLike.postLike; import static com.devin.dev.entity.post.QPostTag.postTag; import static com.devin.dev.entity.post.QSubject.subject; +import static com.devin.dev.entity.reply.QReply.reply; +import static com.devin.dev.entity.reply.QReplyImage.replyImage; +import static com.devin.dev.entity.reply.QReplyLike.replyLike; import static com.devin.dev.entity.user.QUser.user; import static org.springframework.util.StringUtils.hasText; @@ -55,18 +66,12 @@ public Page findPostnamePageByUser(User user, Pageable pageable) { */ @Override - public Page findPostDtoPageWithCondition(PostSearchCondition condition, Pageable pageable) { - QueryResults results = queryFactory - .selectDistinct(new QPostSimpleDto( - post.title, - user.name, - post.content, - post.status, - post.replies.size() - )) + public Page findPostInfoDtoPageByCondition(PostSearchCondition condition, Pageable pageable) { + QueryResults results = queryFactory + .selectDistinct(post) .from(post) - .innerJoin(post.user, user) - .innerJoin(post.tags, postTag) + .leftJoin(post.user, user) + .leftJoin(post.tags, postTag) .where( usernameLike(condition.getUsername()), titleLike(condition.getTitle()), @@ -76,7 +81,9 @@ public Page findPostDtoPageWithCondition(PostSearchCondition cond .limit(pageable.getPageSize()) .fetchResults(); - List content = results.getResults(); + List posts = results.getResults(); + + List content = posts.stream().map(PostInfoDto::new).collect(Collectors.toList()); long total = results.getTotal(); @@ -113,6 +120,31 @@ public Page findAllByTagId(Long id, Pageable pageable) { return new PageImpl<>(content, pageable, total); } + @Override + public Optional findPostDetailsById(Long id, ReplyOrderCondition condition) { + Post result = queryFactory + .select(post) + .from(post) + .innerJoin(post.replies, reply).fetchJoin() + .innerJoin(post.user, user).fetchJoin() + .innerJoin(reply.user, user).fetchJoin() + .where(post.id.eq(id)) + .orderBy( + replyOrder(condition) + ) + .fetchOne(); + + Optional postDetailsDtoOptional; + + postDetailsDtoOptional = result != null ? Optional.of(new PostDetailsDto(result)) : Optional.empty(); + + return postDetailsDtoOptional; + } + + private OrderSpecifier replyOrder(ReplyOrderCondition condition) { + return condition.isLatestDate() ? reply.lastModifiedDate.asc() : reply.likes.size().asc(); + } + private BooleanExpression usernameLike(String username) { return hasText(username) ? user.name.contains(username) : null; } @@ -133,4 +165,5 @@ private BooleanExpression tagsInclude(List tags) { return postTag.in(where);//(where); } + } diff --git a/src/main/java/com/devin/dev/sample/HelloController.java b/src/main/java/com/devin/dev/sample/HelloController.java index 8e7bfe8..949e68a 100644 --- a/src/main/java/com/devin/dev/sample/HelloController.java +++ b/src/main/java/com/devin/dev/sample/HelloController.java @@ -75,13 +75,4 @@ public String getMain() { return "main"; } - @GetMapping("/setting") - public String createSampleData() { - sampleData.createSubjects(); - sampleData.createUsers(); - sampleData.createPosts(); - sampleData.createReplies(); - - return "redirect:/"; - } } diff --git a/src/main/java/com/devin/dev/service/PostService.java b/src/main/java/com/devin/dev/service/PostService.java index d7b1d97..71bd39a 100644 --- a/src/main/java/com/devin/dev/service/PostService.java +++ b/src/main/java/com/devin/dev/service/PostService.java @@ -1,16 +1,15 @@ package com.devin.dev.service; +import com.devin.dev.controller.post.PostForm; import com.devin.dev.controller.post.PostSearchCondition; +import com.devin.dev.controller.reply.ReplyOrderCondition; import com.devin.dev.dto.post.PostDetailsDto; import com.devin.dev.dto.post.PostInfoDto; -import com.devin.dev.dto.post.PostSimpleDto; -import com.devin.dev.entity.post.Post; -import com.devin.dev.entity.post.PostImage; -import com.devin.dev.entity.post.PostTag; -import com.devin.dev.entity.post.Subject; +import com.devin.dev.entity.post.*; import com.devin.dev.entity.user.User; import com.devin.dev.model.DefaultResponse; import com.devin.dev.repository.post.PostImageRepository; +import com.devin.dev.repository.post.PostLikeRepository; import com.devin.dev.repository.post.PostRepository; import com.devin.dev.repository.post.PostTagRepository; import com.devin.dev.repository.reply.ReplyRepository; @@ -18,19 +17,21 @@ import com.devin.dev.repository.reply.ReplyLikeRepository; import com.devin.dev.repository.subject.SubjectRepository; import com.devin.dev.repository.user.UserRepository; +import com.devin.dev.security.JwtAuthTokenProvider; import com.devin.dev.utils.ResponseMessage; import com.devin.dev.utils.StatusCode; import lombok.RequiredArgsConstructor; -import org.springframework.core.convert.converter.Converter; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -39,11 +40,50 @@ public class PostService { private final UserRepository userRepository; private final PostRepository postRepository; private final PostImageRepository postImageRepository; + private final PostLikeRepository postLikeRepository; private final PostTagRepository postTagRepository; private final SubjectRepository subjectRepository; private final ReplyRepository replyRepository; private final ReplyImageRepository replyImageRepository; private final ReplyLikeRepository replyLikeRepository; + private final JwtAuthTokenProvider tokenProvider; + + @Transactional + public DefaultResponse post(HttpServletRequest request, PostForm form) { + String token = tokenProvider.parseToken(request); + Long userId; + if (tokenProvider.validateToken(token)) { + userId = tokenProvider.getUserId(token); + } else { + return new DefaultResponse<>(StatusCode.BAD_REQUEST, ResponseMessage.NOT_FOUND_USER); + } + + // 엔티티 조회. 실패시 에러코드 반환 + Optional userOptional = userRepository.findById(userId); + if (userOptional.isEmpty()) { + return new DefaultResponse<>(StatusCode.BAD_REQUEST, ResponseMessage.NOT_FOUND_USER); + } + User user = userOptional.get(); + List postSubjects = subjectRepository.findByNameIn(form.getPost_tags()); + + // 엔티티 생성 + List postImages = PostImage.createPostImages(form.getPost_images()); + List postTags = PostTag.createPostTags(postSubjects); + Post post = Post.createPostWithImages(user, form.getTitle(), form.getContent(), postTags, postImages); + + // 게시글 작성자 경험치증가 + user.changeExp(User.ExpChangeType.CREATE_POST); + + // 저장 + postRepository.save(post); + postImageRepository.saveAll(postImages); + postTagRepository.saveAll(postTags); + + PostDetailsDto postDetailsDto = new PostDetailsDto(post); + + // 성공 메시지 및 코드 반환 + return new DefaultResponse<>(StatusCode.OK, ResponseMessage.POST_UPLOAD_SUCCESS, postDetailsDto); + } @Transactional public DefaultResponse post(Long userId, String title, String content, List tags, List imagePaths) { @@ -121,12 +161,23 @@ public DefaultResponse editPost(Long userId, Long postId, String title, Strin return new DefaultResponse<>(StatusCode.OK, ResponseMessage.POST_EDIT_SUCCESS); } + @Transactional + public DefaultResponse getPost(Long postId, ReplyOrderCondition replyOrderCondition) { + Optional postOptional = postRepository.findPostDetailsById(postId, replyOrderCondition); + if (postOptional.isEmpty()) { + return new DefaultResponse<>(StatusCode.BAD_REQUEST, ResponseMessage.NOT_FOUND_POST); + } + PostDetailsDto postDetailsDto = postOptional.get(); + + return new DefaultResponse<>(StatusCode.OK, ResponseMessage.FOUND_POST, postDetailsDto); + } + // 게시글 검색 @Transactional - public DefaultResponse> searchPosts(PostSearchCondition condition, Pageable pageable) { - Page postDtos = postRepository.findPostDtoPageWithCondition(condition, pageable); + public DefaultResponse> getPostInfoListByCondition(PostSearchCondition condition, Pageable pageable) { + Page postDtos = postRepository.findPostInfoDtoPageByCondition(condition, pageable); - PageImpl page = new PageImpl<>(postDtos.toList(), pageable, postDtos.getTotalElements()); + PageImpl page = new PageImpl<>(postDtos.toList(), pageable, postDtos.getTotalElements()); return new DefaultResponse<>(StatusCode.OK, ResponseMessage.FOUND_POST, page); } @@ -138,4 +189,24 @@ public DefaultResponse> getPostInfoList(Long id, Pageable page PageImpl postInfoDtosImpl = new PageImpl<>(postInfoDtos.toList(), pageable, postInfoDtos.getTotalElements()); return new DefaultResponse<>(StatusCode.OK, ResponseMessage.FOUND_POST, postInfoDtosImpl); } + + public DefaultResponse deletePost(Long postId) { + Optional postOptional = postRepository.findById(postId); + if (postOptional.isEmpty()) { + return new DefaultResponse<>(StatusCode.BAD_REQUEST, ResponseMessage.NOT_FOUND_POST); + } + Post post = postOptional.get(); + + postImageRepository.deleteAll(post.getImages()); + postTagRepository.deleteAll(post.getTags()); + postLikeRepository.deleteAll(post.getPostLikes()); + replyImageRepository.deleteAll(post.getReplies().stream().flatMap(reply -> reply.getImages().stream()).collect(Collectors.toList())); + replyLikeRepository.deleteAll(post.getReplies().stream().flatMap(reply -> reply.getLikes().stream()).collect(Collectors.toList())); + replyRepository.deleteAll(post.getReplies()); + postRepository.delete(post); + + return new DefaultResponse<>(StatusCode.OK, ResponseMessage.DELETED_POST); + } } + + diff --git a/src/main/java/com/devin/dev/utils/ResponseMessage.java b/src/main/java/com/devin/dev/utils/ResponseMessage.java index d55133c..024bb69 100644 --- a/src/main/java/com/devin/dev/utils/ResponseMessage.java +++ b/src/main/java/com/devin/dev/utils/ResponseMessage.java @@ -20,6 +20,7 @@ public enum ResponseMessage { FOUND_POST("게시글 검색 성공"), POST_UPLOAD_SUCCESS("게시글 등록 성공"), POST_EDIT_SUCCESS("게시글 수정 성공"), + DELETED_POST("게시글 삭제 성공"), REPLY_UPLOAD_SUCCESS("답변 등록 성공"), REPLY_EDIT_SUCCESS("답변 수정 성공"), REPLY_DELETE_SUCCESS("답변 삭제 성공"), diff --git a/src/test/java/com/devin/dev/mvc/PostControllerTest.java b/src/test/java/com/devin/dev/mvc/PostControllerTest.java new file mode 100644 index 0000000..e150ccd --- /dev/null +++ b/src/test/java/com/devin/dev/mvc/PostControllerTest.java @@ -0,0 +1,82 @@ +package com.devin.dev.mvc; + +import com.devin.dev.controller.post.PostForm; +import com.devin.dev.entity.post.Post; +import com.devin.dev.repository.post.PostRepository; +import com.fasterxml.jackson.databind.ObjectMapper; +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.http.MediaType; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import javax.servlet.http.HttpServletRequestWrapper; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +@SpringBootTest +@AutoConfigureMockMvc +class PostControllerTest { + + @Autowired + private MockMvc mvc; + + @Autowired + private PostRepository postRepository; + + private MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + + @Test + @WithMockUser + void requestPostSucceeded() throws Exception { + List posts = postRepository.findByTitle("title_1"); + mvc.perform(get("/postlist/" + posts.get(0).getId())) + .andExpect(status().isOk()) + .andDo(print()); + } + + @Test + @WithMockUser + void requestPostFailed() throws Exception { + mvc.perform(get("/postlist/0")) + .andDo(print()); + } + + @Test + @WithMockUser + void requestDeleteSucceeded() throws Exception { + List posts = postRepository.findByTitle("title_2"); + mvc.perform(delete("/post/" + posts.get(0).getId())) + .andDo(print()); + } + + @Test + @WithMockUser + void requestCreateSucceeded() throws Exception { + PostForm form = new PostForm(); + form.setContent("content_1"); + form.setPost_tags(List.of("tag_0","tag_1")); + form.setPost_images(List.of("img_1", "img_2")); + form.setTitle("title_1"); + mvc.perform( + post("/post").with(request -> { + request.setRemoteUser("USER"); + return request; + }) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(new ObjectMapper().writeValueAsString(form)) + ) + .andDo(print()); + } +} \ No newline at end of file diff --git a/src/test/java/com/devin/dev/repository/PostRepositoryTest.java b/src/test/java/com/devin/dev/repository/PostRepositoryTest.java index 8b284b6..7833fb0 100644 --- a/src/test/java/com/devin/dev/repository/PostRepositoryTest.java +++ b/src/test/java/com/devin/dev/repository/PostRepositoryTest.java @@ -1,6 +1,7 @@ package com.devin.dev.repository; import com.devin.dev.controller.post.PostSearchCondition; +import com.devin.dev.dto.post.PostInfoDto; import com.devin.dev.dto.post.PostSimpleDto; import com.devin.dev.entity.post.Post; import com.devin.dev.entity.post.PostTag; @@ -162,7 +163,7 @@ void findPostDtoPageWithCondition() { condition.setUsername("A"); condition.setTitle("Post"); Pageable pageable = PageRequest.of(0, 4); - Page postDtoPage = postRepository.findPostDtoPageWithCondition(condition, pageable); + Page postDtoPage = postRepository.findPostInfoDtoPageByCondition(condition, pageable); assertThat(postDtoPage).extracting("title").containsExactly("PostA1", "PostA2"); } } \ No newline at end of file diff --git a/src/test/java/com/devin/dev/service/PostServiceTest.java b/src/test/java/com/devin/dev/service/PostServiceTest.java index 2203fb9..6e7cf0b 100644 --- a/src/test/java/com/devin/dev/service/PostServiceTest.java +++ b/src/test/java/com/devin/dev/service/PostServiceTest.java @@ -1,5 +1,7 @@ package com.devin.dev.service; +import com.devin.dev.controller.reply.ReplyOrderCondition; +import com.devin.dev.dto.post.PostDetailsDto; import com.devin.dev.entity.post.Post; import com.devin.dev.entity.post.PostImage; import com.devin.dev.entity.post.PostTag; @@ -10,6 +12,7 @@ import com.devin.dev.repository.post.PostRepository; import com.devin.dev.utils.ResponseMessage; import com.devin.dev.utils.StatusCode; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -34,18 +37,26 @@ class PostServiceTest { @Autowired PostRepository postRepository; - @Test - void postSucceeded() { - Subject subject1 = new Subject("s1"); - Subject subject2 = new Subject("s2"); - Subject subject3 = new Subject("s3"); + Subject subject1; + Subject subject2; + Subject subject3; + User postUser; + + @BeforeEach + void createSampleData() { + subject1 = new Subject("s1"); + subject2 = new Subject("s2"); + subject3 = new Subject("s3"); em.persist(subject1); em.persist(subject2); em.persist(subject3); - User postUser = new User("D", "d@b.com", "passD", "0004", UserStatus.ACTIVE); + postUser = new User("D", "d@b.com", "passD", "0004", UserStatus.ACTIVE); em.persist(postUser); + } + @Test + void postSucceeded() { DefaultResponse response = postService.post(postUser.getId(), "titleA1", "postA1", List.of("s1", "s2"), List.of("p1", "p2", "p3")); assertThat(response.getStatusCode()).isEqualTo(StatusCode.OK); assertThat(response.getResponseMessage()).isEqualTo(ResponseMessage.POST_UPLOAD_SUCCESS); @@ -60,16 +71,6 @@ void postSucceeded() { @Test void postFailed() { - Subject subject1 = new Subject("s1"); - Subject subject2 = new Subject("s2"); - Subject subject3 = new Subject("s3"); - em.persist(subject1); - em.persist(subject2); - em.persist(subject3); - - User postUser = new User("D", "d@b.com", "passD", "0004", UserStatus.ACTIVE); - em.persist(postUser); - DefaultResponse response = postService.post(9999L, "titleA1", "postA1", List.of("s1", "s2"), List.of("p1", "p2", "p3")); assertThat(response.getStatusCode()).isEqualTo(StatusCode.BAD_REQUEST); assertThat(response.getResponseMessage()).isEqualTo(ResponseMessage.NOT_FOUND_USER); @@ -77,16 +78,6 @@ void postFailed() { @Test void editPostTest() { - Subject subject1 = new Subject("s1"); - Subject subject2 = new Subject("s2"); - Subject subject3 = new Subject("s3"); - em.persist(subject1); - em.persist(subject2); - em.persist(subject3); - - User postUser = new User("D", "d@b.com", "passD", "0004", UserStatus.ACTIVE); - em.persist(postUser); - Post post1 = new Post(postUser, "PostC1", "ContentC1"); List postTags = PostTag.createPostTags(List.of(subject1, subject2)); post1.setPostTags(postTags); @@ -121,4 +112,45 @@ void editPostTest() { assertThat(post.getImages()).extracting("path").containsExactly("p4", "p3", "p1", "p2"); assertThat(post.getUser().getExp()).isEqualTo(0); } + + @Test + void getPostSucceeded() { + Post post1 = new Post(postUser, "PostC1", "ContentC1"); + List postTags = PostTag.createPostTags(List.of(subject1, subject2)); + post1.setPostTags(postTags); + List postImages = PostImage.createPostImages(List.of("p1", "p2", "p3")); + post1.setPostImages(postImages); + postTags.forEach(em::persist); + postImages.forEach(em::persist); + em.persist(post1); + + ReplyOrderCondition replyOrderCondition = new ReplyOrderCondition(); + replyOrderCondition.setLatestDate(true); + + DefaultResponse response = postService.getPost(post1.getId(), replyOrderCondition); + assertThat(response.getStatusCode()).isEqualTo(StatusCode.OK); + assertThat(response.getResponseMessage()).isEqualTo(ResponseMessage.FOUND_POST); + + PostDetailsDto postDto = response.getData(); + assertThat(postDto.getTitle()).isEqualTo("PostC1"); + assertThat(postDto.getPublisher_name()).isEqualTo("D"); + assertThat(postDto.getPost_images()).containsExactly("p1","p2","p3"); + } + + @Test + void deleteSucceeded() { + Post post1 = new Post(postUser, "PostC1", "ContentC1"); + List postTags = PostTag.createPostTags(List.of(subject1, subject2)); + post1.setPostTags(postTags); + List postImages = PostImage.createPostImages(List.of("p1", "p2", "p3")); + post1.setPostImages(postImages); + postTags.forEach(em::persist); + postImages.forEach(em::persist); + em.persist(post1); + + postService.deletePost(post1.getId()); + + Post post = em.find(Post.class, post1.getId()); + assertThat(post).isNull(); + } } \ No newline at end of file