From 9f8f0dfe8d68fa95d2d08b2ba83a8df0db465870 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Thu, 17 Sep 2020 17:57:50 +0900 Subject: [PATCH 01/33] =?UTF-8?q?feat:=20ArticleReport=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../saebyeok/domain/report/ArticleReport.java | 45 +++++++++++++++++++ .../report/ArticleReportRepository.java | 4 ++ 2 files changed, 49 insertions(+) create mode 100644 src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java create mode 100644 src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java new file mode 100644 index 00000000..2361f5c1 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java @@ -0,0 +1,45 @@ +package com.saebyeok.saebyeok.domain.report; + +import com.saebyeok.saebyeok.domain.Article; +import com.saebyeok.saebyeok.domain.Member; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@EntityListeners(AuditingEntityListener.class) +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Entity +public class ArticleReport { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "REPORT_ID") + private Long id; + + private String content; + + @ManyToOne + private Member member; + + @ManyToOne + private Article article; + + @ManyToOne + private ReportCategory reportCategory; + + @CreatedDate + private LocalDateTime createdDate; + + private boolean isFinished = Boolean.FALSE; + + public void finish() { + this.isFinished = true; + } +} diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java new file mode 100644 index 00000000..35098867 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java @@ -0,0 +1,4 @@ +package com.saebyeok.saebyeok.domain.report; + +public class ArticleReportRepository { +} From f5a377af8dd100692881df946d6beffd3760c80e Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Sat, 19 Sep 2020 16:00:11 +0900 Subject: [PATCH 02/33] =?UTF-8?q?feat:=20ArticleReport,=20CommentReport=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../saebyeok/domain/report/ArticleReport.java | 8 +++ .../report/ArticleReportRepository.java | 4 +- .../saebyeok/domain/report/CommentReport.java | 53 +++++++++++++++++++ .../report/CommentReportRepository.java | 6 +++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java create mode 100644 src/main/java/com/saebyeok/saebyeok/domain/report/CommentReportRepository.java diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java index 2361f5c1..b793c603 100644 --- a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java @@ -5,6 +5,8 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -25,12 +27,18 @@ public class ArticleReport { private String content; + @OnDelete(action = OnDeleteAction.CASCADE) + @JoinColumn(name = "MEMBER_ID", nullable = false) @ManyToOne private Member member; + @OnDelete(action = OnDeleteAction.CASCADE) + @JoinColumn(name = "ARTICLE_ID", nullable = false) @ManyToOne private Article article; + @OnDelete(action = OnDeleteAction.CASCADE) + @JoinColumn(name = "REPORT_CATEGORY_ID", nullable = false) @ManyToOne private ReportCategory reportCategory; diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java index 35098867..c897f184 100644 --- a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReportRepository.java @@ -1,4 +1,6 @@ package com.saebyeok.saebyeok.domain.report; -public class ArticleReportRepository { +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ArticleReportRepository extends JpaRepository { } diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java b/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java new file mode 100644 index 00000000..4b8d5ac3 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java @@ -0,0 +1,53 @@ +package com.saebyeok.saebyeok.domain.report; + +import com.saebyeok.saebyeok.domain.Comment; +import com.saebyeok.saebyeok.domain.Member; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.OnDelete; +import org.hibernate.annotations.OnDeleteAction; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@EntityListeners(AuditingEntityListener.class) +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Entity +public class CommentReport { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "REPORT_ID") + private Long id; + + private String content; + + @OnDelete(action = OnDeleteAction.CASCADE) + @JoinColumn(name = "MEMBER_ID", nullable = false) + @ManyToOne + private Member member; + + @OnDelete(action = OnDeleteAction.CASCADE) + @JoinColumn(name = "COMMENT_ID", nullable = false) + @ManyToOne + private Comment comment; + + @OnDelete(action = OnDeleteAction.CASCADE) + @JoinColumn(name = "REPORT_CATEGORY_ID", nullable = false) + @ManyToOne + private ReportCategory reportCategory; + + @CreatedDate + private LocalDateTime createdDate; + + private boolean isFinished = Boolean.FALSE; + + public void finish() { + this.isFinished = true; + } +} diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReportRepository.java b/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReportRepository.java new file mode 100644 index 00000000..013b50ea --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReportRepository.java @@ -0,0 +1,6 @@ +package com.saebyeok.saebyeok.domain.report; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentReportRepository extends JpaRepository { +} From 919171440eeb66e30e9856d59fa58972ce38e053 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Mon, 21 Sep 2020 12:55:02 +0900 Subject: [PATCH 03/33] =?UTF-8?q?feat:=20ArticleReport=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=9D=B8=EC=88=98=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 인수 테스트 중 Mock Controller에서 대응할 수 없는 내용 일부를 주석처리함 - ArticleReport 생성을 위한 ArticleReportCreateRequest DTO 구현 - ArticleReportResponse 구현 - ReportController에 ArticleReport에 대한 매핑 구현 --- src/frontend/src/api/modules/report.js | 2 +- .../saebyeok/controller/ReportController.java | 40 ++++- .../saebyeok/domain/report/ArticleReport.java | 2 +- .../report/ArticleReportCreateRequest.java | 19 +++ .../dto/report/ArticleReportResponse.java | 29 ++++ .../saebyeok/acceptance/AcceptanceTest.java | 4 +- .../acceptance/ReportAcceptanceTest.java | 138 ++++++++++++++++++ .../ReportCategoryAcceptanceTest.java | 2 +- .../controller/ReportControllerTest.java | 4 +- 9 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java create mode 100644 src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java create mode 100644 src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java diff --git a/src/frontend/src/api/modules/report.js b/src/frontend/src/api/modules/report.js index 1096c933..23fb8539 100644 --- a/src/frontend/src/api/modules/report.js +++ b/src/frontend/src/api/modules/report.js @@ -4,7 +4,7 @@ const BASE_URL = '/reports'; const ReportService = { getCategories() { - return ApiService.get(`/report/categories`); + return ApiService.get(`/reports/categories`); }, create(report) { return ApiService.post(`${BASE_URL}`, report); diff --git a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java index e613aeaf..0faa6fc4 100644 --- a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java +++ b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java @@ -1,13 +1,17 @@ package com.saebyeok.saebyeok.controller; +import com.saebyeok.saebyeok.controller.resolver.LoginMember; +import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; +import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; import com.saebyeok.saebyeok.service.report.ReportService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import java.net.URI; +import java.util.Arrays; import java.util.List; @RequestMapping("/api") @@ -16,10 +20,36 @@ public class ReportController { private final ReportService reportService; - @GetMapping("/report/categories") + @GetMapping("/reports/categories") public ResponseEntity> getReportCategories() { List reportCategoryResponses = reportService.getReportCategories(); - + return ResponseEntity.ok(reportCategoryResponses); } + + @PostMapping("/reports/article") + public ResponseEntity createArticleReport(@LoginMember Member member, @RequestBody ArticleReportCreateRequest request) { + return ResponseEntity. + created(URI.create("/reports/" + 1L)). + build(); + } + + @GetMapping("/reports/article") + public ResponseEntity> getArticleReports(@LoginMember Member member) { + List reportResponses = Arrays.asList(new ArticleReportResponse(1L, "이 게시물을 신고합니다.", "", new ReportCategoryResponse(1L, "", ""), false)); + + return ResponseEntity.ok(reportResponses); + } + + @GetMapping("/reports/article/{reportId}") + public ResponseEntity readArticleReport(@LoginMember Member member, @PathVariable Long reportId) { + ArticleReportResponse articleReportResponse = new ArticleReportResponse(1L, "이 게시물을 신고합니다.", "", new ReportCategoryResponse(1L, "", ""), false); + + return ResponseEntity.ok(articleReportResponse); + } + + @DeleteMapping("/reports/article/{reportId}") + public ResponseEntity deleteArticleReport(@LoginMember Member member, @PathVariable Long reportId) { + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java index b793c603..5c6c6d40 100644 --- a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java @@ -45,7 +45,7 @@ public class ArticleReport { @CreatedDate private LocalDateTime createdDate; - private boolean isFinished = Boolean.FALSE; + private Boolean isFinished = Boolean.FALSE; public void finish() { this.isFinished = true; diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java new file mode 100644 index 00000000..3f549170 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java @@ -0,0 +1,19 @@ +package com.saebyeok.saebyeok.dto.report; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ArticleReportCreateRequest { + private String content; + + @NotNull(message = "신고할 게시물을 반드시 선택해 주셔야 해요.") + private Long articleId; + @NotNull(message = "신고 분류는 반드시 선택되어야 해요.") + private Long reportCategoryId; +} diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java new file mode 100644 index 00000000..93c3beb9 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java @@ -0,0 +1,29 @@ +package com.saebyeok.saebyeok.dto.report; + +import com.saebyeok.saebyeok.domain.report.ArticleReport; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ArticleReportResponse { + private Long id; + private String content; + private String articleContent; + private ReportCategoryResponse reportCategory; + private Boolean isFinished; + + public ArticleReportResponse(ArticleReport articleReport) { + this.id = articleReport.getId(); + this.content = articleReport.getContent(); + this.articleContent = articleReport.getArticle().getContent(); + this.reportCategory = new ReportCategoryResponse(articleReport.getReportCategory()); + this.isFinished = articleReport.getIsFinished(); + } + + public boolean getIsFinished() { + return isFinished; + } +} diff --git a/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java b/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java index 8fe975e9..91af515a 100644 --- a/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java @@ -70,9 +70,9 @@ public void createArticle(String content, Long emotionId, List subEmotionI body(params). contentType(MediaType.APPLICATION_JSON_VALUE). accept(MediaType.APPLICATION_JSON_VALUE). - when(). + when(). post(API + "/articles"). - then(). + then(). log().all(). statusCode(HttpStatus.CREATED.value()); //@formatter:on diff --git a/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java new file mode 100644 index 00000000..ab2282a8 --- /dev/null +++ b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java @@ -0,0 +1,138 @@ +package com.saebyeok.saebyeok.acceptance; + +import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ReportAcceptanceTest extends AcceptanceTest { + private static final Long REPORT_ID = 1L; + private static final Long REPORT_CATEGORY_ID = 1L; + private static final Long REPORT_ARTICLE_ID = 1L; + private static final Long REPORT_COMMENT_ID = 1L; + private static final String REPORT_CONTENT = "이 게시물을 신고합니다."; + private static final Boolean isFinished = false; + + + /** + * Scenario: 신고를 추가, 조회, 삭제할 수 있다. + *

+ * given 게시물 신고가 하나도 없다. + * when 게시물 신고를 하나 추가한다. + * then 게시물 신고가 1개 생긴다. + *

+ * given 댓글 신고가 하나도 없다. + * when 댓글 신고를 하나 추가한다. + * then 댓글 신고가 1개 생긴다. + *

+ * given 게시물 신고가 1개 존재한다. + * when 게시물 신고를 조회한다. + * then 조회된 게시물 신고 값이 존재하는 신고 값과 일치한다. + *

+ * given 댓글 신고가 1개 존재한다. + * when 댓글 신고를 조회한다. + * then 조회된 댓글 신고 값이 존재하는 신고 값과 일치한다. + *

+ * given 게시물 신고가 하나 있다. + * when 해당 게시물 신고를 완료 처리한다. + * then 해당 게시물 신고를 조회하면 완료된 것으로 값이 설정되어 있다. + *

+ * given 댓글 신고가 하나 있다. + * when 해당 댓글 신고를 완료 처리한다. + * then 해당 댓글 신고를 조회하면 완료된 것으로 값이 설정되어 있다. + */ + + @Test + void manageArticleReport() { + //given 신고가 하나도 없다. + List reports = getArticleReports(); + //assertThat(reports).isEmpty(); + + //when 신고를 하나 추가한다. + createArticleReport(); + + //then 신고가 1개 생긴다. + reports = getArticleReports(); + assertThat(reports).hasSize(1); + + //when 신고를 조회한다. + ArticleReportResponse reportResponse = readArticleReport(REPORT_ID); + + //then 조회된 신고 값이 존재하는 신고 값과 일치한다. + assertThat(reportResponse.getContent()).isEqualTo(REPORT_CONTENT); + + //when 신고를 완료 처리한다. + deleteArticleReport(REPORT_ID); + //then 해당 신고를 조회하면 완료된 것으로 값이 설정되어 있다. + reportResponse = readArticleReport(REPORT_ID); + //assertThat(reportResponse.getIsFinished()).isTrue(); + } + + private void createArticleReport() { + Map params = new HashMap<>(); + params.put("content", REPORT_CONTENT); + params.put("articleId", REPORT_ARTICLE_ID); + params.put("reportCategoryId", REPORT_CATEGORY_ID); + + //@formatter:off + given(). + auth().oauth2(TOKEN). + body(params). + contentType(MediaType.APPLICATION_JSON_VALUE). + accept(MediaType.APPLICATION_JSON_VALUE). + when(). + post(API + "/reports/article"). + then(). + log().all(). + statusCode(HttpStatus.CREATED.value()); + //@formatter:on + } + + private List getArticleReports() { + //@formatter:off + return + given(). + auth().oauth2(TOKEN). + when(). + get(API + "/reports/article"). + then(). + log().all(). + extract(). + jsonPath(). + getList(".", ArticleReportResponse.class); + //@formatter:on + } + + private ArticleReportResponse readArticleReport(Long id) { + //@formatter:off + return + given(). + auth().oauth2(TOKEN). + accept(MediaType.APPLICATION_JSON_VALUE). + when(). + get(API + "/reports/article/" + id). + then(). + log().all(). + extract(). + as(ArticleReportResponse.class); + //@formatter:on + } + + private void deleteArticleReport(Long id) { + //@formatter:off + given(). + auth().oauth2(TOKEN). + when(). + delete(API + "/reports/article/" + id). + then(). + log().all(). + statusCode(HttpStatus.NO_CONTENT.value()); + //@formatter:on + } +} diff --git a/src/test/java/com/saebyeok/saebyeok/acceptance/ReportCategoryAcceptanceTest.java b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportCategoryAcceptanceTest.java index 24e15431..d0d3294f 100644 --- a/src/test/java/com/saebyeok/saebyeok/acceptance/ReportCategoryAcceptanceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportCategoryAcceptanceTest.java @@ -36,7 +36,7 @@ private List getReportCategories() { given(). auth().oauth2(TOKEN). when(). - get(API + "/report/categories"). + get(API + "/reports/categories"). then(). log().all(). extract(). diff --git a/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java b/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java index b7012dd3..399c35e5 100644 --- a/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java +++ b/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java @@ -44,12 +44,12 @@ void setUp(WebApplicationContext context) { this.reportCategoryResponse = new ReportCategoryResponse(TEST_CATEGORY_ID, TEST_CATEGORY_NAME, TEST_CATEGORY_CONTENT); } - @DisplayName("'/report/categories'로 get 요청을 보내면 ReportCategory 리스트를 받는다.") + @DisplayName("'/reports/categories'로 get 요청을 보내면 ReportCategory 리스트를 받는다.") @Test void getReportCategoriesTest() throws Exception { when(reportService.getReportCategories()).thenReturn(Arrays.asList(this.reportCategoryResponse)); - this.mockMvc.perform(get(API + "/report/categories"). + this.mockMvc.perform(get(API + "/reports/categories"). accept(MediaType.APPLICATION_JSON_VALUE)). andExpect(jsonPath("$", hasSize(1))). andExpect(jsonPath("$[0].name").value(TEST_CATEGORY_NAME)); From 5c1229ce0cb9cbca49392f11a88be44b6a8057de Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Mon, 21 Sep 2020 17:35:47 +0900 Subject: [PATCH 04/33] =?UTF-8?q?feat:=20ArticleReport=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20Domain/DTO=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ArticleReportCreateRequest에 대응하는 ArticleReport의 생성자 구현 - ArticleReportResponse가 Article의 Id를 필드로 가지도록 구현 - ReportCategoryNotFoundException과 ReportNotFoundException 구현 --- .../saebyeok/controller/GlobalExceptionAdvice.java | 2 ++ .../saebyeok/saebyeok/domain/report/ArticleReport.java | 7 +++++++ .../saebyeok/dto/report/ArticleReportCreateRequest.java | 8 ++++++++ .../saebyeok/dto/report/ArticleReportResponse.java | 4 ++-- .../exception/ReportCategoryNotFoundException.java | 7 +++++++ .../saebyeok/exception/ReportNotFoundException.java | 7 +++++++ 6 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/saebyeok/saebyeok/exception/ReportCategoryNotFoundException.java create mode 100644 src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java diff --git a/src/main/java/com/saebyeok/saebyeok/controller/GlobalExceptionAdvice.java b/src/main/java/com/saebyeok/saebyeok/controller/GlobalExceptionAdvice.java index bd7e4048..5ac1c2c3 100644 --- a/src/main/java/com/saebyeok/saebyeok/controller/GlobalExceptionAdvice.java +++ b/src/main/java/com/saebyeok/saebyeok/controller/GlobalExceptionAdvice.java @@ -20,6 +20,8 @@ public class GlobalExceptionAdvice { CommentNotFoundException.class, ArticleNotFoundException.class, EmotionNotFoundException.class, + ReportNotFoundException.class, + ReportCategoryNotFoundException.class, IllegalAccessException.class, DuplicateArticleLikeException.class, DuplicateCommentLikeException.class}) diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java index 5c6c6d40..38291dfb 100644 --- a/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/ArticleReport.java @@ -47,6 +47,13 @@ public class ArticleReport { private Boolean isFinished = Boolean.FALSE; + public ArticleReport(String content, Member member, Article article, ReportCategory reportCategory) { + this.content = content; + this.member = member; + this.article = article; + this.reportCategory = reportCategory; + } + public void finish() { this.isFinished = true; } diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java index 3f549170..5558df75 100644 --- a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportCreateRequest.java @@ -1,5 +1,9 @@ package com.saebyeok.saebyeok.dto.report; +import com.saebyeok.saebyeok.domain.Article; +import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.domain.report.ReportCategory; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -16,4 +20,8 @@ public class ArticleReportCreateRequest { private Long articleId; @NotNull(message = "신고 분류는 반드시 선택되어야 해요.") private Long reportCategoryId; + + public ArticleReport toArticleReport(Member member, Article article, ReportCategory reportCategory) { + return new ArticleReport(content, member, article, reportCategory); + } } diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java index 93c3beb9..be9b80d2 100644 --- a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java @@ -11,14 +11,14 @@ public class ArticleReportResponse { private Long id; private String content; - private String articleContent; + private Long articleId; private ReportCategoryResponse reportCategory; private Boolean isFinished; public ArticleReportResponse(ArticleReport articleReport) { this.id = articleReport.getId(); this.content = articleReport.getContent(); - this.articleContent = articleReport.getArticle().getContent(); + this.articleId = articleReport.getArticle().getId(); this.reportCategory = new ReportCategoryResponse(articleReport.getReportCategory()); this.isFinished = articleReport.getIsFinished(); } diff --git a/src/main/java/com/saebyeok/saebyeok/exception/ReportCategoryNotFoundException.java b/src/main/java/com/saebyeok/saebyeok/exception/ReportCategoryNotFoundException.java new file mode 100644 index 00000000..fdc4a751 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/exception/ReportCategoryNotFoundException.java @@ -0,0 +1,7 @@ +package com.saebyeok.saebyeok.exception; + +public class ReportCategoryNotFoundException extends RuntimeException { + public ReportCategoryNotFoundException(Long reportCategoryId) { + super(reportCategoryId + "에 해당하는 신고 분류를 찾을 수 없습니다."); + } +} diff --git a/src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java b/src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java new file mode 100644 index 00000000..74bffc47 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java @@ -0,0 +1,7 @@ +package com.saebyeok.saebyeok.exception; + +public class ReportNotFoundException extends RuntimeException { + public ReportNotFoundException(Long reportCategoryId) { + super(reportCategoryId + "에 해당하는 신고를 이력을 찾을 수 없습니다."); + } +} From a197b9e836142cf8aaa431e0d96d08290eea2915 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Mon, 21 Sep 2020 19:01:39 +0900 Subject: [PATCH 05/33] =?UTF-8?q?feat:=20ArticleReport=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC/?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ArticleReport에 대한 컨트롤러 테스트 구현 - ArticleReport에 대한 서비스 테스트 구현 - 각 테스트에, ReportNotFoundException이 발생하는 경우(read, delete)에 대한 예외 테스트 구현 --- .../saebyeok/controller/ReportController.java | 12 +- .../exception/ReportNotFoundException.java | 2 +- .../service/report/ReportService.java | 47 ++++++++ .../acceptance/ReportAcceptanceTest.java | 16 ++- .../controller/ReportControllerTest.java | 106 +++++++++++++++++- .../saebyeok/service/ReportServiceTest.java | 95 +++++++++++++++- src/test/resources/truncate.sql | 4 +- 7 files changed, 270 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java index 0faa6fc4..72a152ba 100644 --- a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java +++ b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java @@ -2,6 +2,7 @@ import com.saebyeok.saebyeok.controller.resolver.LoginMember; import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.report.ArticleReport; import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; @@ -11,7 +12,6 @@ import org.springframework.web.bind.annotation.*; import java.net.URI; -import java.util.Arrays; import java.util.List; @RequestMapping("/api") @@ -29,27 +29,31 @@ public ResponseEntity> getReportCategories() { @PostMapping("/reports/article") public ResponseEntity createArticleReport(@LoginMember Member member, @RequestBody ArticleReportCreateRequest request) { + ArticleReport articleReport = reportService.createArticleReport(member, request); + return ResponseEntity. - created(URI.create("/reports/" + 1L)). + created(URI.create("/reports/" + articleReport.getId())). build(); } @GetMapping("/reports/article") public ResponseEntity> getArticleReports(@LoginMember Member member) { - List reportResponses = Arrays.asList(new ArticleReportResponse(1L, "이 게시물을 신고합니다.", "", new ReportCategoryResponse(1L, "", ""), false)); + List reportResponses = reportService.getArticleReports(member); return ResponseEntity.ok(reportResponses); } @GetMapping("/reports/article/{reportId}") public ResponseEntity readArticleReport(@LoginMember Member member, @PathVariable Long reportId) { - ArticleReportResponse articleReportResponse = new ArticleReportResponse(1L, "이 게시물을 신고합니다.", "", new ReportCategoryResponse(1L, "", ""), false); + ArticleReportResponse articleReportResponse = reportService.readArticleReport(member, reportId); return ResponseEntity.ok(articleReportResponse); } @DeleteMapping("/reports/article/{reportId}") public ResponseEntity deleteArticleReport(@LoginMember Member member, @PathVariable Long reportId) { + reportService.deleteArticleReport(member, reportId); + return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java b/src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java index 74bffc47..d43dbf33 100644 --- a/src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java +++ b/src/main/java/com/saebyeok/saebyeok/exception/ReportNotFoundException.java @@ -2,6 +2,6 @@ public class ReportNotFoundException extends RuntimeException { public ReportNotFoundException(Long reportCategoryId) { - super(reportCategoryId + "에 해당하는 신고를 이력을 찾을 수 없습니다."); + super(reportCategoryId + "에 해당하는 신고 이력을 찾을 수 없습니다."); } } diff --git a/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java b/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java index c6aade3c..0cf9a30d 100644 --- a/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java +++ b/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java @@ -1,9 +1,21 @@ package com.saebyeok.saebyeok.service.report; +import com.saebyeok.saebyeok.domain.Article; +import com.saebyeok.saebyeok.domain.ArticleRepository; +import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.domain.report.ArticleReportRepository; +import com.saebyeok.saebyeok.domain.report.ReportCategory; import com.saebyeok.saebyeok.domain.report.ReportCategoryRepository; +import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; +import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; +import com.saebyeok.saebyeok.exception.ArticleNotFoundException; +import com.saebyeok.saebyeok.exception.ReportCategoryNotFoundException; +import com.saebyeok.saebyeok.exception.ReportNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; @@ -12,7 +24,9 @@ @Service public class ReportService { + private final ArticleRepository articleRepository; private final ReportCategoryRepository reportCategoryRepository; + private final ArticleReportRepository articleReportRepository; public List getReportCategories() { return reportCategoryRepository.findAll(). @@ -20,4 +34,37 @@ public List getReportCategories() { map(ReportCategoryResponse::new). collect(Collectors.toList()); } + + @Transactional + public ArticleReport createArticleReport(Member member, ArticleReportCreateRequest request) { + ReportCategory reportCategory = reportCategoryRepository.findById(request.getReportCategoryId()). + orElseThrow(() -> new ReportCategoryNotFoundException(request.getReportCategoryId())); + Article article = articleRepository.findById(request.getArticleId()). + orElseThrow(() -> new ArticleNotFoundException(request.getArticleId())); + + ArticleReport articleReport = request.toArticleReport(member, article, reportCategory); + + return articleReportRepository.save(articleReport); + } + + public List getArticleReports(Member member) { + return articleReportRepository.findAll(). + stream(). + map(ArticleReportResponse::new). + collect(Collectors.toList()); + } + + public ArticleReportResponse readArticleReport(Member member, Long reportId) { + ArticleReport articleReport = articleReportRepository.findById(reportId). + orElseThrow(() -> new ReportNotFoundException(reportId)); + return new ArticleReportResponse(articleReport); + } + + @Transactional + public void deleteArticleReport(Member member, Long reportId) { + ArticleReport articleReport = articleReportRepository.findById(reportId). + orElseThrow(() -> new ReportNotFoundException(reportId)); + + articleReport.finish(); + } } diff --git a/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java index ab2282a8..0480641f 100644 --- a/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java @@ -1,10 +1,12 @@ package com.saebyeok.saebyeok.acceptance; import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -12,6 +14,8 @@ import static org.assertj.core.api.Assertions.assertThat; public class ReportAcceptanceTest extends AcceptanceTest { + private static final Long EMOTION_ID = 1L; + private static final List SUB_EMOTION_IDS = Arrays.asList(1L, 2L); private static final Long REPORT_ID = 1L; private static final Long REPORT_CATEGORY_ID = 1L; private static final Long REPORT_ARTICLE_ID = 1L; @@ -19,6 +23,13 @@ public class ReportAcceptanceTest extends AcceptanceTest { private static final String REPORT_CONTENT = "이 게시물을 신고합니다."; private static final Boolean isFinished = false; + @BeforeEach + public void setUp() { + super.setUp(); + + createArticle("content", EMOTION_ID, SUB_EMOTION_IDS, true); + } + /** * Scenario: 신고를 추가, 조회, 삭제할 수 있다. @@ -52,7 +63,7 @@ public class ReportAcceptanceTest extends AcceptanceTest { void manageArticleReport() { //given 신고가 하나도 없다. List reports = getArticleReports(); - //assertThat(reports).isEmpty(); + assertThat(reports).isEmpty(); //when 신고를 하나 추가한다. createArticleReport(); @@ -69,9 +80,10 @@ void manageArticleReport() { //when 신고를 완료 처리한다. deleteArticleReport(REPORT_ID); + //then 해당 신고를 조회하면 완료된 것으로 값이 설정되어 있다. reportResponse = readArticleReport(REPORT_ID); - //assertThat(reportResponse.getIsFinished()).isTrue(); + assertThat(reportResponse.getIsFinished()).isTrue(); } private void createArticleReport() { diff --git a/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java b/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java index 399c35e5..769a8e0f 100644 --- a/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java +++ b/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java @@ -1,6 +1,12 @@ package com.saebyeok.saebyeok.controller; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; +import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; +import com.saebyeok.saebyeok.exception.ReportNotFoundException; import com.saebyeok.saebyeok.service.report.ReportService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -13,27 +19,42 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import static org.hamcrest.Matchers.hasSize; -import static org.mockito.Mockito.when; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WithUserDetails(userDetailsServiceBeanName = "userService", value = "123456789") @SpringBootTest public class ReportControllerTest { private static final String API = "/api"; + public static final String TEST_ARTICLE_REPORT_CONTENT = "게시물에 대한 신고 본문입니다."; private static final Long TEST_CATEGORY_ID = 1L; private static final String TEST_CATEGORY_NAME = "광고 게시물"; private static final String TEST_CATEGORY_CONTENT = "상업적 목적을 가진 게시물에 해당합니다."; + public static final Long TEST_ARTICLE_ID = 1L; + public static final Long TEST_ARTICLE_REPORT_ID_1 = 1L; + public static final Long TEST_ARTICLE_REPORT_ID_2 = 2L; + public static final Long TEST_INVALID_REPORT_ID = 10000L; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @MockBean private ReportService reportService; private MockMvc mockMvc; private ReportCategoryResponse reportCategoryResponse; + private List articleReportResponses; @BeforeEach void setUp(WebApplicationContext context) { @@ -42,16 +63,97 @@ void setUp(WebApplicationContext context) { build(); this.reportCategoryResponse = new ReportCategoryResponse(TEST_CATEGORY_ID, TEST_CATEGORY_NAME, TEST_CATEGORY_CONTENT); + + articleReportResponses = new ArrayList<>(); + articleReportResponses.add(new ArticleReportResponse(TEST_ARTICLE_REPORT_ID_1, TEST_ARTICLE_REPORT_CONTENT, TEST_ARTICLE_ID, reportCategoryResponse, false)); + articleReportResponses.add(new ArticleReportResponse(TEST_ARTICLE_REPORT_ID_2, TEST_ARTICLE_REPORT_CONTENT, TEST_ARTICLE_ID, reportCategoryResponse, false)); } @DisplayName("'/reports/categories'로 get 요청을 보내면 ReportCategory 리스트를 받는다.") @Test void getReportCategoriesTest() throws Exception { - when(reportService.getReportCategories()).thenReturn(Arrays.asList(this.reportCategoryResponse)); + when(reportService.getReportCategories()).thenReturn(Arrays.asList(reportCategoryResponse)); this.mockMvc.perform(get(API + "/reports/categories"). accept(MediaType.APPLICATION_JSON_VALUE)). andExpect(jsonPath("$", hasSize(1))). andExpect(jsonPath("$[0].name").value(TEST_CATEGORY_NAME)); } + + @DisplayName("'/reports/article'로 post 요청을 보내면 글을 생성한다") + @Test + void createArticleReportTest() throws Exception { + ArticleReportCreateRequest request = new ArticleReportCreateRequest(TEST_ARTICLE_REPORT_CONTENT, TEST_ARTICLE_ID, TEST_CATEGORY_ID); + String requestAsString = OBJECT_MAPPER.writeValueAsString(request); + ArticleReport articleReport = new ArticleReport(TEST_ARTICLE_REPORT_CONTENT, null, null, null); + + when(reportService.createArticleReport(any(Member.class), any(ArticleReportCreateRequest.class))).thenReturn(articleReport); + + this.mockMvc.perform(post(API + "/reports/article"). + content(requestAsString). + contentType(MediaType.APPLICATION_JSON)). + andExpect(status().isCreated()). + andDo(print()); + } + + @DisplayName("'/reports/article'로 get 요청을 보내면 신고 목록을 반환한다.") + @Test + void getArticleReportsTest() throws Exception { + when(reportService.getArticleReports(any(Member.class))).thenReturn(articleReportResponses); + + this.mockMvc.perform(get(API + "/reports/article"). + accept(MediaType.APPLICATION_JSON_VALUE)). + andExpect(jsonPath("$", hasSize(2))). + andExpect(jsonPath("$[0].id").value(TEST_ARTICLE_REPORT_ID_1)). + andExpect(jsonPath("$[0].content").value(TEST_ARTICLE_REPORT_CONTENT)). + andExpect(jsonPath("$[0].articleId").value(TEST_ARTICLE_ID)). + andExpect(jsonPath("$[1].id").value(TEST_ARTICLE_REPORT_ID_2)). + andExpect(jsonPath("$[1].content").value(TEST_ARTICLE_REPORT_CONTENT)). + andExpect(jsonPath("$[1].articleId").value(TEST_ARTICLE_ID)); + } + + @DisplayName("ID로 개별 신고 조회를 요청하면 해당 신고를 반환한다.") + @Test + void readArticleReportTest() throws Exception { + when(reportService.readArticleReport(any(Member.class), eq(TEST_ARTICLE_REPORT_ID_1))).thenReturn(articleReportResponses.get(0)); + + this.mockMvc.perform(get(API + "/reports/article/" + TEST_ARTICLE_REPORT_ID_1). + contentType(MediaType.APPLICATION_JSON)). + andExpect(status().isOk()). + andExpect(jsonPath("$.id").value(TEST_ARTICLE_REPORT_ID_1)). + andExpect(jsonPath("$.content").value(TEST_ARTICLE_REPORT_CONTENT)). + andExpect(jsonPath("$.articleId").value(TEST_ARTICLE_ID)). + andExpect(jsonPath("$.isFinished").value(false)); + } + + @DisplayName("에외 테스트 : 없는 ID로 신고 조회를 요청하면, ReportNotFoundException이 발생한다.") + @Test + void readArticleReportExceptionTest() throws Exception { + when(reportService.readArticleReport(any(Member.class), eq(TEST_INVALID_REPORT_ID))). + thenThrow(ReportNotFoundException.class); + + this.mockMvc.perform(get(API + "/reports/article/" + TEST_INVALID_REPORT_ID). + contentType(MediaType.APPLICATION_JSON)). + andExpect(status().isBadRequest()); + } + + @DisplayName("ID로 신고 삭제를 요청하면 해당 신고의 flag를 조정해 soft delete 처리한다.") + @Test + void deleteArticleReportTest() throws Exception { + doNothing().when(reportService).deleteArticleReport(any(Member.class), eq(TEST_ARTICLE_REPORT_ID_1)); + + this.mockMvc.perform(delete(API + "/reports/article/" + TEST_ARTICLE_REPORT_ID_1)). + andExpect(status().isNoContent()); + } + + @DisplayName("예외 테스트 : 없는 ID로 신고 삭제를 요청하면 ReportNotFoundException이 발생한다.") + @Test + void deleteArticleReportExceptionTest() throws Exception { + doThrow(new ReportNotFoundException(TEST_INVALID_REPORT_ID)). + when(reportService).deleteArticleReport(any(Member.class), eq(TEST_INVALID_REPORT_ID)); + + this.mockMvc.perform(delete(API + "/reports/article/" + TEST_INVALID_REPORT_ID). + contentType(MediaType.APPLICATION_JSON)). + andExpect(status().isBadRequest()); + } } diff --git a/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java b/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java index 644dab76..07e077b4 100644 --- a/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java @@ -1,8 +1,16 @@ package com.saebyeok.saebyeok.service; +import com.saebyeok.saebyeok.domain.Article; +import com.saebyeok.saebyeok.domain.ArticleRepository; +import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.Role; +import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.domain.report.ArticleReportRepository; import com.saebyeok.saebyeok.domain.report.ReportCategory; import com.saebyeok.saebyeok.domain.report.ReportCategoryRepository; +import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; +import com.saebyeok.saebyeok.exception.ReportNotFoundException; import com.saebyeok.saebyeok.service.report.ReportService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -10,30 +18,56 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.context.jdbc.Sql; +import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; +@Sql("/truncate.sql") @ExtendWith(MockitoExtension.class) public class ReportServiceTest { + public static final String ARTICLE_REPORT_CONTENT = "이 게시물을 신고합니다"; + private static final Long MEMBER_ID = 1L; + private static final String MEMBER_OAUTH_ID = "123456789"; + private static final String MEMBER_LOGIN_METHOD = "naver"; private static final Long CATEGORY_ID = 1L; private static final String CATEGORY_NAME = "광고 게시물"; private static final String CATEGORY_CONTENT = "상업적 목적을 가진 게시물에 해당합니다."; + private static final boolean IS_DELETED = false; + private static final Long ARTICLE_ID = 1L; + private static final Long INVALID_REPORT_ID = 10000L; + private static final Long ARTICLE_REPORT_ID = 1L; private ReportService reportService; - + @Mock + private ArticleRepository articleRepository; @Mock private ReportCategoryRepository reportCategoryRepository; + @Mock + private ArticleReportRepository articleReportRepository; private ReportCategory reportCategory; + private Member member; + private ArticleReport articleReport; @BeforeEach void setUp() { - reportService = new ReportService(reportCategoryRepository); + member = new Member(MEMBER_ID, MEMBER_OAUTH_ID, MEMBER_LOGIN_METHOD, LocalDateTime.now(), IS_DELETED, Role.USER, new ArrayList<>()); + Article article = new Article(ARTICLE_ID, "게시물", member, LocalDateTime.now(), false, false, null, new ArrayList<>()); + + reportService = new ReportService(articleRepository, reportCategoryRepository, articleReportRepository); reportCategory = new ReportCategory(CATEGORY_ID, CATEGORY_NAME, CATEGORY_CONTENT); + + articleReport = new ArticleReport(ARTICLE_ID, ARTICLE_REPORT_CONTENT, member, article, reportCategory, LocalDateTime.now(), false); } @DisplayName("전체 ReportCategory를 조회하면 ReportCategory 목록이 반환된다") @@ -50,4 +84,61 @@ void getReportCategories() { assertThat(reportCategoryResponses.get(0).getName()).isEqualTo(CATEGORY_NAME); assertThat(reportCategoryResponses.get(0).getContent()).isEqualTo(CATEGORY_CONTENT); } + + @DisplayName("전체 게시물 신고를 조회하면 게시물 신고 목록이 반환된다") + @Test + void getArticleReportsTest() { + List articleReports = Arrays.asList(articleReport); + when(articleReportRepository.findAll()).thenReturn(articleReports); + + List articleReportResponses = reportService.getArticleReports(member); + + assertThat(articleReportResponses).hasSize(1); + assertThat(articleReportResponses.get(0).getContent()).isEqualTo(ARTICLE_REPORT_CONTENT); + assertThat(articleReportResponses.get(0).getArticleId()).isEqualTo(ARTICLE_ID); + assertThat(articleReportResponses.get(0).getIsFinished()).isEqualTo(false); + } + + @DisplayName("ID로 개별 게시물 신고를 요청하면 해당 신고가 반환된다") + @Test + void readArticleReportTest() { + when(articleReportRepository.findById(any())).thenReturn(Optional.of(articleReport)); + + ArticleReportResponse articleReportResponse = reportService.readArticleReport(member, ARTICLE_REPORT_ID); + + assertThat(articleReportResponse).isNotNull(); + assertThat(articleReportResponse.getContent()).isEqualTo(ARTICLE_REPORT_CONTENT); + assertThat(articleReportResponse.getArticleId()).isEqualTo(ARTICLE_ID); + assertThat(articleReportResponse.getIsFinished()).isEqualTo(false); + } + + @DisplayName("예외 테스트 : ID로 잘못된 게시물 신고를 요청하면 ReportNotFoundException이 발생한다") + @Test + void readArticleReportExceptionTest() { + when(articleReportRepository.findById(any())).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> reportService.readArticleReport(member, INVALID_REPORT_ID)). + isInstanceOf(ReportNotFoundException.class). + hasMessage(INVALID_REPORT_ID + "에 해당하는 신고 이력을 찾을 수 없습니다."); + } + + @DisplayName("ID로 게시물 신고에 대한 삭제를 요청하면, 해당 신고를 삭제한다") + @Test + void deleteArticleReportTest() { + when(articleReportRepository.findById(any())).thenReturn(Optional.of(articleReport)); + reportService.deleteArticleReport(member, ARTICLE_REPORT_ID); + + assertThat(articleReport.getIsFinished()).isTrue(); + } + + @DisplayName("예외 테스트 : ID로 잘못된 게시물 신고에 대한 삭제를 요청하면 ReportNotFoundException이 발생한다") + @Test + void deleteArticleReportExceptionTest() { + doThrow(new ReportNotFoundException(INVALID_REPORT_ID)). + when(articleReportRepository).findById(INVALID_REPORT_ID); + + assertThatThrownBy(() -> reportService.readArticleReport(member, INVALID_REPORT_ID)). + isInstanceOf(ReportNotFoundException.class). + hasMessage(INVALID_REPORT_ID + "에 해당하는 신고 이력을 찾을 수 없습니다."); + } } diff --git a/src/test/resources/truncate.sql b/src/test/resources/truncate.sql index d14a90cb..d275f54e 100644 --- a/src/test/resources/truncate.sql +++ b/src/test/resources/truncate.sql @@ -9,4 +9,6 @@ SET FOREIGN_KEY_CHECKS=0; TRUNCATE TABLE EMOTION; SET FOREIGN_KEY_CHECKS=1; TRUNCATE TABLE ARTICLE_EMOTION; -TRUNCATE TABLE ARTICLE_SUB_EMOTION; \ No newline at end of file +TRUNCATE TABLE ARTICLE_SUB_EMOTION; +TRUNCATE TABLE ARTICLE_REPORT; +TRUNCATE TABLE COMMENT_REPORT; \ No newline at end of file From 0a2117b105e466eae0b41203e00954c346582c29 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Mon, 21 Sep 2020 19:14:53 +0900 Subject: [PATCH 06/33] =?UTF-8?q?feat:=20ArticleReport=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20Repository=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 28 +++--- .../domain/ArticleReportRepositoryTest.java | 94 +++++++++++++++++++ .../domain/ReportCategoryRepositoryTest.java | 2 +- 3 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java diff --git a/build.gradle b/build.gradle index 55bbb5f9..63f80974 100644 --- a/build.gradle +++ b/build.gradle @@ -83,17 +83,17 @@ bootJar { } } -task setUp(type: NpmTask) { - description = "Install Node.js packages" - args = ['install'] - inputs.files file('package.json') - outputs.files file('node_modules') -} - -task buildFrontEnd(type: NpmTask, dependsOn: setUp) { - description = "Build vue.js" - args = ['run', 'build'] -} - - -processResources.dependsOn 'buildFrontEnd' \ No newline at end of file +//task setUp(type: NpmTask) { +// description = "Install Node.js packages" +// args = ['install'] +// inputs.files file('package.json') +// outputs.files file('node_modules') +//} +// +//task buildFrontEnd(type: NpmTask, dependsOn: setUp) { +// description = "Build vue.js" +// args = ['run', 'build'] +//} +// +// +//processResources.dependsOn 'buildFrontEnd' \ No newline at end of file diff --git a/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java new file mode 100644 index 00000000..ec659693 --- /dev/null +++ b/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java @@ -0,0 +1,94 @@ +package com.saebyeok.saebyeok.domain; + +import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.domain.report.ArticleReportRepository; +import com.saebyeok.saebyeok.domain.report.ReportCategory; +import com.saebyeok.saebyeok.domain.report.ReportCategoryRepository; +import com.saebyeok.saebyeok.exception.ReportNotFoundException; +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.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.transaction.Transactional; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ArticleReportRepositoryTest { + + @Autowired + private ArticleReportRepository articleReportRepository; + + @Autowired + private MemberRepository memberRepository; + + @Autowired + private ArticleRepository articleRepository; + + @Autowired + private ReportCategoryRepository reportCategoryRepository; + + private Article article; + private Member member; + private ReportCategory reportCategory; + + private ArticleReport articleReport1; + private ArticleReport articleReport2; + private ArticleReport articleReport3; + + @BeforeEach + @Transactional + void setUp() { + reportCategory = new ReportCategory(3L, "분류3", "설명3"); + reportCategoryRepository.save(reportCategory); + article = new Article("내용1", true); + articleRepository.save(article); + member = new Member(1L, "123456789", "naver", LocalDateTime.now(), false, Role.USER, new ArrayList<>()); + memberRepository.save(member); + + articleReport1 = new ArticleReport("신고 내용1", member, article, reportCategory); + articleReport2 = new ArticleReport("신고 내용2", member, article, reportCategory); + articleReport3 = new ArticleReport("신고 내용3", member, article, reportCategory); + articleReportRepository.save(articleReport1); + articleReportRepository.save(articleReport2); + articleReportRepository.save(articleReport3); + } + + @DisplayName("게시글을 저장한다") + @Test + void saveTest() { + ArticleReport newArticleReport = new ArticleReport("신교 내용 4", member, article, reportCategory); + int articleReportSize = articleReportRepository.findAll().size(); + + articleReportRepository.save(newArticleReport); + + List articleReports = articleReportRepository.findAll(); + assertThat(articleReports).hasSize(articleReportSize + 1).contains(newArticleReport); + } + + @DisplayName("전체 ArticleReport를 조회한다") + @Test + void findAllTest() { + List articleReports = articleReportRepository.findAll(); + assertThat(articleReports). + hasSize(3). + extracting("content"). + containsOnly(articleReport1.getContent(), articleReport2.getContent(), articleReport3.getContent()); + } + + @DisplayName("ID로 개별 ArticleReport를 조회한다") + @ValueSource(longs = {1L, 2L, 3L}) + @ParameterizedTest + void findByIdTest(Long id) { + ArticleReport articleReport = articleReportRepository.findById(id). + orElseThrow(() -> new ReportNotFoundException(id)); + + assertThat(articleReport).isNotNull(); + assertThat(articleReport.getId()).isEqualTo(id); + } +} diff --git a/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java index f0abce56..10de69e7 100644 --- a/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java +++ b/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java @@ -41,7 +41,7 @@ void setUp() { @DisplayName("전체 ReportCategory를 조회한다") @Test void findAllTest() { - List reportCategories = this.reportCategoryRepository.findAll(); + List reportCategories = reportCategoryRepository.findAll(); assertThat(reportCategories). hasSize(3). extracting("name"). From fe96ce80dbcf5933ec54138a0768c89046e61864 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Mon, 21 Sep 2020 22:08:49 +0900 Subject: [PATCH 07/33] =?UTF-8?q?feat:=20ArticleReport=EC=9D=98=20DTO=20?= =?UTF-8?q?=EB=B0=8F=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=9D=98=EC=A1=B4=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD,=20Comment=20DTO=20?= =?UTF-8?q?=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ArticleReportResponse에 ArticleResponse가 포함되어 신고 게시물에 대한 정보를 활용할 수 있도록 로직 추가 - ReportService가 ArticleService를 autowired하여 사용함. ArticleService의 readMemberArticle 메서드를 활용하여 response를 만들고, 별도로 Article이 필요한 create 로직 부분만 findArticleById 메서드를 추가하여 활용함. - CommentService 역시 find로직이 필요하게 되어 미리 만들어 둠 - CommentReportCreateRequest 및 CommentReportResponse 구현. 이 중 CommentReportResponse는 CommentResponse를 포함하도록 설계함 --- build.gradle | 28 +++++++++---------- .../saebyeok/domain/report/CommentReport.java | 9 +++++- .../dto/report/ArticleReportResponse.java | 11 +++----- .../report/CommentReportCreateRequest.java | 27 ++++++++++++++++++ .../dto/report/CommentReportResponse.java | 26 +++++++++++++++++ .../saebyeok/service/ArticleService.java | 5 ++++ .../saebyeok/service/CommentService.java | 10 +++---- .../service/report/ReportService.java | 20 ++++++++----- 8 files changed, 102 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportCreateRequest.java create mode 100644 src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java diff --git a/build.gradle b/build.gradle index 63f80974..55bbb5f9 100644 --- a/build.gradle +++ b/build.gradle @@ -83,17 +83,17 @@ bootJar { } } -//task setUp(type: NpmTask) { -// description = "Install Node.js packages" -// args = ['install'] -// inputs.files file('package.json') -// outputs.files file('node_modules') -//} -// -//task buildFrontEnd(type: NpmTask, dependsOn: setUp) { -// description = "Build vue.js" -// args = ['run', 'build'] -//} -// -// -//processResources.dependsOn 'buildFrontEnd' \ No newline at end of file +task setUp(type: NpmTask) { + description = "Install Node.js packages" + args = ['install'] + inputs.files file('package.json') + outputs.files file('node_modules') +} + +task buildFrontEnd(type: NpmTask, dependsOn: setUp) { + description = "Build vue.js" + args = ['run', 'build'] +} + + +processResources.dependsOn 'buildFrontEnd' \ No newline at end of file diff --git a/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java b/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java index 4b8d5ac3..7e4185c0 100644 --- a/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java +++ b/src/main/java/com/saebyeok/saebyeok/domain/report/CommentReport.java @@ -45,7 +45,14 @@ public class CommentReport { @CreatedDate private LocalDateTime createdDate; - private boolean isFinished = Boolean.FALSE; + private Boolean isFinished = Boolean.FALSE; + + public CommentReport(String content, Member member, Comment comment, ReportCategory reportCategory) { + this.content = content; + this.member = member; + this.comment = comment; + this.reportCategory = reportCategory; + } public void finish() { this.isFinished = true; diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java index be9b80d2..3efef245 100644 --- a/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/ArticleReportResponse.java @@ -1,6 +1,7 @@ package com.saebyeok.saebyeok.dto.report; import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.dto.ArticleResponse; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,19 +12,15 @@ public class ArticleReportResponse { private Long id; private String content; - private Long articleId; + private ArticleResponse article; private ReportCategoryResponse reportCategory; private Boolean isFinished; - public ArticleReportResponse(ArticleReport articleReport) { + public ArticleReportResponse(ArticleReport articleReport, ArticleResponse articleResponse) { this.id = articleReport.getId(); this.content = articleReport.getContent(); - this.articleId = articleReport.getArticle().getId(); + this.article = articleResponse; this.reportCategory = new ReportCategoryResponse(articleReport.getReportCategory()); this.isFinished = articleReport.getIsFinished(); } - - public boolean getIsFinished() { - return isFinished; - } } diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportCreateRequest.java b/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportCreateRequest.java new file mode 100644 index 00000000..f45d5c2f --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportCreateRequest.java @@ -0,0 +1,27 @@ +package com.saebyeok.saebyeok.dto.report; + +import com.saebyeok.saebyeok.domain.Comment; +import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.report.CommentReport; +import com.saebyeok.saebyeok.domain.report.ReportCategory; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CommentReportCreateRequest { + private String content; + + @NotNull(message = "신고할 댓글을 반드시 선택해 주셔야 해요.") + private Long commentId; + @NotNull(message = "신고 분류는 반드시 선택되어야 해요.") + private Long reportCategoryId; + + public CommentReport toCommentReport(Member member, Comment comment, ReportCategory reportCategory) { + return new CommentReport(content, member, comment, reportCategory); + } +} diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java b/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java new file mode 100644 index 00000000..1433ac69 --- /dev/null +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java @@ -0,0 +1,26 @@ +package com.saebyeok.saebyeok.dto.report; + +import com.saebyeok.saebyeok.domain.report.CommentReport; +import com.saebyeok.saebyeok.dto.CommentResponse; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CommentReportResponse { + private Long id; + private String content; + private CommentResponse comment; + private ReportCategoryResponse reportCategoryResponse; + private Boolean isFinished; + + public CommentReportResponse(CommentReport commentReport, CommentResponse commentResponse) { + this.id = commentReport.getId(); + this.content = commentReport.getContent(); + this.comment = commentResponse; + this.reportCategoryResponse = new ReportCategoryResponse(commentReport.getReportCategory()); + this.isFinished = commentReport.getIsFinished(); + } +} diff --git a/src/main/java/com/saebyeok/saebyeok/service/ArticleService.java b/src/main/java/com/saebyeok/saebyeok/service/ArticleService.java index 571bb2cd..f1485edf 100644 --- a/src/main/java/com/saebyeok/saebyeok/service/ArticleService.java +++ b/src/main/java/com/saebyeok/saebyeok/service/ArticleService.java @@ -117,4 +117,9 @@ private List filterArticles(Member member, List

articl }). collect(Collectors.toList()); } + + public Article findArticleById(Long articleId) { + return articleRepository.findById(articleId) + .orElseThrow(() -> new ArticleNotFoundException(articleId)); + } } diff --git a/src/main/java/com/saebyeok/saebyeok/service/CommentService.java b/src/main/java/com/saebyeok/saebyeok/service/CommentService.java index cfcaa697..566fb39f 100644 --- a/src/main/java/com/saebyeok/saebyeok/service/CommentService.java +++ b/src/main/java/com/saebyeok/saebyeok/service/CommentService.java @@ -42,6 +42,11 @@ public List findAllCommentsBy(Member member) { return commentRepository.findAllByMemberAndIsDeleted(member, false); } + public Comment findCommentById(Long commentId) { + return commentRepository.findById(commentId). + orElseThrow(() -> new CommentNotFoundException(commentId)); + } + @Transactional public void deleteComment(Member member, Long commentId) throws IllegalAccessException { Comment comment = commentRepository.findById(commentId) @@ -52,9 +57,4 @@ public void deleteComment(Member member, Long commentId) throws IllegalAccessExc comment.setIsDeleted(true); commentRepository.save(comment); } - - @Transactional - public void deleteCommentsByArticle(Article article) { - commentRepository.deleteAll(article.getComments()); - } } diff --git a/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java b/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java index 0cf9a30d..85712284 100644 --- a/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java +++ b/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java @@ -1,18 +1,18 @@ package com.saebyeok.saebyeok.service.report; import com.saebyeok.saebyeok.domain.Article; -import com.saebyeok.saebyeok.domain.ArticleRepository; import com.saebyeok.saebyeok.domain.Member; import com.saebyeok.saebyeok.domain.report.ArticleReport; import com.saebyeok.saebyeok.domain.report.ArticleReportRepository; import com.saebyeok.saebyeok.domain.report.ReportCategory; import com.saebyeok.saebyeok.domain.report.ReportCategoryRepository; +import com.saebyeok.saebyeok.dto.ArticleResponse; import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; -import com.saebyeok.saebyeok.exception.ArticleNotFoundException; import com.saebyeok.saebyeok.exception.ReportCategoryNotFoundException; import com.saebyeok.saebyeok.exception.ReportNotFoundException; +import com.saebyeok.saebyeok.service.ArticleService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,7 +24,7 @@ @Service public class ReportService { - private final ArticleRepository articleRepository; + private final ArticleService articleService; private final ReportCategoryRepository reportCategoryRepository; private final ArticleReportRepository articleReportRepository; @@ -39,8 +39,7 @@ public List getReportCategories() { public ArticleReport createArticleReport(Member member, ArticleReportCreateRequest request) { ReportCategory reportCategory = reportCategoryRepository.findById(request.getReportCategoryId()). orElseThrow(() -> new ReportCategoryNotFoundException(request.getReportCategoryId())); - Article article = articleRepository.findById(request.getArticleId()). - orElseThrow(() -> new ArticleNotFoundException(request.getArticleId())); + Article article = articleService.findArticleById(request.getArticleId()); ArticleReport articleReport = request.toArticleReport(member, article, reportCategory); @@ -50,14 +49,21 @@ public ArticleReport createArticleReport(Member member, ArticleReportCreateReque public List getArticleReports(Member member) { return articleReportRepository.findAll(). stream(). - map(ArticleReportResponse::new). + map(articleReport -> { + Long articleId = articleReport.getArticle().getId(); + ArticleResponse articleResponse = articleService.readMemberArticle(member, articleId); + return new ArticleReportResponse(articleReport, articleResponse); + }). collect(Collectors.toList()); } public ArticleReportResponse readArticleReport(Member member, Long reportId) { ArticleReport articleReport = articleReportRepository.findById(reportId). orElseThrow(() -> new ReportNotFoundException(reportId)); - return new ArticleReportResponse(articleReport); + Long articleId = articleReport.getArticle().getId(); + ArticleResponse articleResponse = articleService.readMemberArticle(member, articleId); + + return new ArticleReportResponse(articleReport, articleResponse); } @Transactional From 54c30124ea2597d856dcf1a5dc43db495c008f90 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Mon, 21 Sep 2020 22:59:17 +0900 Subject: [PATCH 08/33] =?UTF-8?q?feat:=20CommentReport=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=9D=B8=EC=88=98=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84,=20CommentReport=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20Controller=EC=99=80=20Service=EC=97=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CommentReport에 대한 인수 테스트를 ReportAcceptanceTest에 추가, 기존 코드를 최대한 재활용함 - ReportController에 /reports/comment 연산 4가지를 추가 - ReportService에 CommentReport에 대한 연산 4가지 추가 - 모든 테스트가 통과하도록 테스트 세부사항 수정 --- .../saebyeok/controller/ReportController.java | 37 +++++++- .../service/report/ReportService.java | 51 ++++++++-- .../saebyeok/acceptance/AcceptanceTest.java | 26 ++++++ .../acceptance/CommentAcceptanceTest.java | 27 +----- .../acceptance/ReportAcceptanceTest.java | 92 ++++++++++++++++++- .../controller/ReportControllerTest.java | 28 ++++-- .../domain/ArticleReportRepositoryTest.java | 30 +++--- .../domain/ArticleRepositoryTest.java | 1 - .../domain/ReportCategoryRepositoryTest.java | 1 + .../saebyeok/service/ReportServiceTest.java | 16 ++-- 10 files changed, 246 insertions(+), 63 deletions(-) diff --git a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java index 72a152ba..0179e24e 100644 --- a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java +++ b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java @@ -3,9 +3,8 @@ import com.saebyeok.saebyeok.controller.resolver.LoginMember; import com.saebyeok.saebyeok.domain.Member; import com.saebyeok.saebyeok.domain.report.ArticleReport; -import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; -import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; -import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; +import com.saebyeok.saebyeok.domain.report.CommentReport; +import com.saebyeok.saebyeok.dto.report.*; import com.saebyeok.saebyeok.service.report.ReportService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -32,7 +31,7 @@ public ResponseEntity createArticleReport(@LoginMember Member member, @Req ArticleReport articleReport = reportService.createArticleReport(member, request); return ResponseEntity. - created(URI.create("/reports/" + articleReport.getId())). + created(URI.create("/reports/article" + articleReport.getId())). build(); } @@ -56,4 +55,34 @@ public ResponseEntity deleteArticleReport(@LoginMember Member member, @Pat return ResponseEntity.noContent().build(); } + + @PostMapping("/reports/comment") + public ResponseEntity createCommentReport(@LoginMember Member member, @RequestBody CommentReportCreateRequest request) { + CommentReport commentReport = reportService.createCommentReport(member, request); + + return ResponseEntity. + created(URI.create("/reports/comment" + commentReport.getId())). + build(); + } + + @GetMapping("/reports/comment") + public ResponseEntity> getCommentReports(@LoginMember Member member) { + List reportResponses = reportService.getCommentReports(member); + + return ResponseEntity.ok(reportResponses); + } + + @GetMapping("/reports/comment/{reportId}") + public ResponseEntity readCommentReport(@LoginMember Member member, @PathVariable Long reportId) { + CommentReportResponse commentReportResponse = reportService.readCommentReport(member, reportId); + + return ResponseEntity.ok(commentReportResponse); + } + + @DeleteMapping("/reports/comment/{reportId}") + public ResponseEntity deleteCommentReport(@LoginMember Member member, @PathVariable Long reportId) { + reportService.deleteCommentReport(member, reportId); + + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java b/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java index 85712284..6151a63e 100644 --- a/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java +++ b/src/main/java/com/saebyeok/saebyeok/service/report/ReportService.java @@ -1,18 +1,16 @@ package com.saebyeok.saebyeok.service.report; import com.saebyeok.saebyeok.domain.Article; +import com.saebyeok.saebyeok.domain.Comment; import com.saebyeok.saebyeok.domain.Member; -import com.saebyeok.saebyeok.domain.report.ArticleReport; -import com.saebyeok.saebyeok.domain.report.ArticleReportRepository; -import com.saebyeok.saebyeok.domain.report.ReportCategory; -import com.saebyeok.saebyeok.domain.report.ReportCategoryRepository; +import com.saebyeok.saebyeok.domain.report.*; import com.saebyeok.saebyeok.dto.ArticleResponse; -import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; -import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; -import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; +import com.saebyeok.saebyeok.dto.CommentResponse; +import com.saebyeok.saebyeok.dto.report.*; import com.saebyeok.saebyeok.exception.ReportCategoryNotFoundException; import com.saebyeok.saebyeok.exception.ReportNotFoundException; import com.saebyeok.saebyeok.service.ArticleService; +import com.saebyeok.saebyeok.service.CommentService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,8 +23,10 @@ public class ReportService { private final ArticleService articleService; + private final CommentService commentService; private final ReportCategoryRepository reportCategoryRepository; private final ArticleReportRepository articleReportRepository; + private final CommentReportRepository commentReportRepository; public List getReportCategories() { return reportCategoryRepository.findAll(). @@ -73,4 +73,41 @@ public void deleteArticleReport(Member member, Long reportId) { articleReport.finish(); } + + @Transactional + public CommentReport createCommentReport(Member member, CommentReportCreateRequest request) { + ReportCategory reportCategory = reportCategoryRepository.findById(request.getReportCategoryId()). + orElseThrow(() -> new ReportCategoryNotFoundException(request.getReportCategoryId())); + Comment comment = commentService.findCommentById(request.getCommentId()); + + CommentReport commentReport = request.toCommentReport(member, comment, reportCategory); + + return commentReportRepository.save(commentReport); + } + + public List getCommentReports(Member member) { + return commentReportRepository.findAll(). + stream(). + map(commentReport -> { + CommentResponse commentResponse = new CommentResponse(commentReport.getComment(), member); + return new CommentReportResponse(commentReport, commentResponse); + }). + collect(Collectors.toList()); + } + + public CommentReportResponse readCommentReport(Member member, Long reportId) { + CommentReport commentReport = commentReportRepository.findById(reportId). + orElseThrow(() -> new ReportNotFoundException(reportId)); + CommentResponse commentResponse = new CommentResponse(commentReport.getComment(), member); + + return new CommentReportResponse(commentReport, commentResponse); + } + + @Transactional + public void deleteCommentReport(Member member, Long reportId) { + CommentReport commentReport = commentReportRepository.findById(reportId). + orElseThrow(() -> new ReportNotFoundException(reportId)); + + commentReport.finish(); + } } diff --git a/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java b/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java index 91af515a..186b20dc 100644 --- a/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/acceptance/AcceptanceTest.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.Map; +import static com.saebyeok.saebyeok.domain.CommentTest.TEST_NICKNAME; + @WithUserDetails("123456789") @Sql({"/truncate.sql", "/emotion.sql"}) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -77,4 +79,28 @@ public void createArticle(String content, Long emotionId, List subEmotionI statusCode(HttpStatus.CREATED.value()); //@formatter:on } + + + public void createComment(Long createdId) { + //@formatter:off + Map params = new HashMap<>(); + params.put("memberId", MEMBER_ID); + params.put("nickname", TEST_NICKNAME); + params.put("articleId", ARTICLE_ID); + params.put("isDeleted", false); + params.put("content", "새벽 좋아요"); + + given(). + auth().oauth2(TOKEN). + body(params). + contentType(MediaType.APPLICATION_JSON_VALUE). + accept(MediaType.APPLICATION_JSON_VALUE). + when(). + post(API + "/articles/" + ARTICLE_ID + "/comments"). + then(). + log().all(). + statusCode(HttpStatus.CREATED.value()). + header("Location","/articles/" + ARTICLE_ID + "/comments/" + createdId); + //@formatter:on + } } \ No newline at end of file diff --git a/src/test/java/com/saebyeok/saebyeok/acceptance/CommentAcceptanceTest.java b/src/test/java/com/saebyeok/saebyeok/acceptance/CommentAcceptanceTest.java index c6596a7e..9f81fb42 100644 --- a/src/test/java/com/saebyeok/saebyeok/acceptance/CommentAcceptanceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/acceptance/CommentAcceptanceTest.java @@ -31,10 +31,7 @@ public void setUp() { createArticle("content", EMOTION_ID, SUB_EMOTION_IDS, true); params = new HashMap<>(); - params.put("memberId", MEMBER_ID); - params.put("nickname", TEST_NICKNAME); - params.put("articleId", ARTICLE_ID); - params.put("isDeleted", false); + } /** @@ -122,26 +119,12 @@ void manageComment() { .contains("에 해당하는 댓글을 찾을 수 없습니다!"); } - private void createComment(Long createdId) { - //@formatter:off - params.put("content", "새벽 좋아요"); - - given(). - auth().oauth2(TOKEN). - body(params). - contentType(MediaType.APPLICATION_JSON_VALUE). - accept(MediaType.APPLICATION_JSON_VALUE). - when(). - post(API + "/articles/" + ARTICLE_ID + "/comments"). - then(). - log().all(). - statusCode(HttpStatus.CREATED.value()). - header("Location","/articles/" + ARTICLE_ID + "/comments/" + createdId); - //@formatter:on - } - private ExceptionResponse createInvalidComment(String content) { //@formatter:off + params.put("memberId", MEMBER_ID); + params.put("nickname", TEST_NICKNAME); + params.put("articleId", ARTICLE_ID); + params.put("isDeleted", false); params.put("content", content); return diff --git a/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java index 0480641f..154566de 100644 --- a/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/acceptance/ReportAcceptanceTest.java @@ -1,6 +1,7 @@ package com.saebyeok.saebyeok.acceptance; import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; +import com.saebyeok.saebyeok.dto.report.CommentReportResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; @@ -21,13 +22,13 @@ public class ReportAcceptanceTest extends AcceptanceTest { private static final Long REPORT_ARTICLE_ID = 1L; private static final Long REPORT_COMMENT_ID = 1L; private static final String REPORT_CONTENT = "이 게시물을 신고합니다."; - private static final Boolean isFinished = false; @BeforeEach public void setUp() { super.setUp(); createArticle("content", EMOTION_ID, SUB_EMOTION_IDS, true); + createComment(REPORT_COMMENT_ID); } @@ -86,6 +87,33 @@ void manageArticleReport() { assertThat(reportResponse.getIsFinished()).isTrue(); } + @Test + void manageCommentReport() { + //given 신고가 하나도 없다. + List reports = getCommentReports(); + assertThat(reports).isEmpty(); + + //when 신고를 하나 추가한다. + createCommentReport(); + + //then 신고가 1개 생긴다. + reports = getCommentReports(); + assertThat(reports).hasSize(1); + + //when 신고를 조회한다. + CommentReportResponse reportResponse = readCommentReport(REPORT_ID); + + //then 조회된 신고 값이 존재하는 신고 값과 일치한다. + assertThat(reportResponse.getContent()).isEqualTo(REPORT_CONTENT); + + //when 신고를 완료 처리한다. + deleteCommentReport(REPORT_ID); + + //then 해당 신고를 조회하면 완료된 것으로 값이 설정되어 있다. + reportResponse = readCommentReport(REPORT_ID); + assertThat(reportResponse.getIsFinished()).isTrue(); + } + private void createArticleReport() { Map params = new HashMap<>(); params.put("content", REPORT_CONTENT); @@ -147,4 +175,66 @@ private void deleteArticleReport(Long id) { statusCode(HttpStatus.NO_CONTENT.value()); //@formatter:on } + + private void createCommentReport() { + Map params = new HashMap<>(); + params.put("content", REPORT_CONTENT); + params.put("commentId", REPORT_COMMENT_ID); + params.put("reportCategoryId", REPORT_CATEGORY_ID); + + //@formatter:off + given(). + auth().oauth2(TOKEN). + body(params). + contentType(MediaType.APPLICATION_JSON_VALUE). + accept(MediaType.APPLICATION_JSON_VALUE). + when(). + post(API + "/reports/comment"). + then(). + log().all(). + statusCode(HttpStatus.CREATED.value()); + //@formatter:on + } + + private List getCommentReports() { + //@formatter:off + return + given(). + auth().oauth2(TOKEN). + when(). + get(API + "/reports/comment"). + then(). + log().all(). + extract(). + jsonPath(). + getList(".", CommentReportResponse.class); + //@formatter:on + } + + private CommentReportResponse readCommentReport(Long id) { + //@formatter:off + return + given(). + auth().oauth2(TOKEN). + accept(MediaType.APPLICATION_JSON_VALUE). + when(). + get(API + "/reports/comment/" + id). + then(). + log().all(). + extract(). + as(CommentReportResponse.class); + //@formatter:on + } + + private void deleteCommentReport(Long id) { + //@formatter:off + given(). + auth().oauth2(TOKEN). + when(). + delete(API + "/reports/comment/" + id). + then(). + log().all(). + statusCode(HttpStatus.NO_CONTENT.value()); + //@formatter:on + } } diff --git a/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java b/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java index 769a8e0f..a765a3da 100644 --- a/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java +++ b/src/test/java/com/saebyeok/saebyeok/controller/ReportControllerTest.java @@ -1,8 +1,13 @@ package com.saebyeok.saebyeok.controller; import com.fasterxml.jackson.databind.ObjectMapper; +import com.saebyeok.saebyeok.domain.Emotion; import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.SubEmotion; import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.dto.ArticleResponse; +import com.saebyeok.saebyeok.dto.EmotionResponse; +import com.saebyeok.saebyeok.dto.SubEmotionResponse; import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; @@ -19,9 +24,11 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import static org.hamcrest.Matchers.hasSize; import static org.mockito.ArgumentMatchers.any; @@ -47,6 +54,15 @@ public class ReportControllerTest { public static final Long TEST_ARTICLE_REPORT_ID_1 = 1L; public static final Long TEST_ARTICLE_REPORT_ID_2 = 2L; public static final Long TEST_INVALID_REPORT_ID = 10000L; + public static final boolean TEST_IS_LIKED_BY_ME = false; + private static final Emotion TEST_EMOTION = new Emotion(1L, "기뻐요", "이미지 리소스"); + private static final List TEST_SUB_EMOTIONS = Arrays.asList(new SubEmotion(1L, "행복해요"), new SubEmotion(2L, "설레요")); + private static final Boolean TEST_IS_MINE = true; + private static final Boolean TEST_IS_COMMENT_ALLOWED = true; + private static final Long TEST_ID = 1L; + private static final String TEST_CONTENT = "내용1"; + private static final Long TEST_LIKES_COUNT = 10L; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @MockBean @@ -64,9 +80,12 @@ void setUp(WebApplicationContext context) { this.reportCategoryResponse = new ReportCategoryResponse(TEST_CATEGORY_ID, TEST_CATEGORY_NAME, TEST_CATEGORY_CONTENT); + List subEmotionResponses = TEST_SUB_EMOTIONS.stream().map(SubEmotionResponse::new).collect(Collectors.toList()); + ArticleResponse articleResponse = new ArticleResponse(TEST_ID, TEST_CONTENT, LocalDateTime.now(), new EmotionResponse(TEST_EMOTION), subEmotionResponses, TEST_IS_COMMENT_ALLOWED, TEST_IS_MINE, TEST_LIKES_COUNT, TEST_IS_LIKED_BY_ME, null); + articleReportResponses = new ArrayList<>(); - articleReportResponses.add(new ArticleReportResponse(TEST_ARTICLE_REPORT_ID_1, TEST_ARTICLE_REPORT_CONTENT, TEST_ARTICLE_ID, reportCategoryResponse, false)); - articleReportResponses.add(new ArticleReportResponse(TEST_ARTICLE_REPORT_ID_2, TEST_ARTICLE_REPORT_CONTENT, TEST_ARTICLE_ID, reportCategoryResponse, false)); + articleReportResponses.add(new ArticleReportResponse(TEST_ARTICLE_REPORT_ID_1, TEST_ARTICLE_REPORT_CONTENT, articleResponse, reportCategoryResponse, false)); + articleReportResponses.add(new ArticleReportResponse(TEST_ARTICLE_REPORT_ID_2, TEST_ARTICLE_REPORT_CONTENT, articleResponse, reportCategoryResponse, false)); } @DisplayName("'/reports/categories'로 get 요청을 보내면 ReportCategory 리스트를 받는다.") @@ -106,10 +125,8 @@ void getArticleReportsTest() throws Exception { andExpect(jsonPath("$", hasSize(2))). andExpect(jsonPath("$[0].id").value(TEST_ARTICLE_REPORT_ID_1)). andExpect(jsonPath("$[0].content").value(TEST_ARTICLE_REPORT_CONTENT)). - andExpect(jsonPath("$[0].articleId").value(TEST_ARTICLE_ID)). andExpect(jsonPath("$[1].id").value(TEST_ARTICLE_REPORT_ID_2)). - andExpect(jsonPath("$[1].content").value(TEST_ARTICLE_REPORT_CONTENT)). - andExpect(jsonPath("$[1].articleId").value(TEST_ARTICLE_ID)); + andExpect(jsonPath("$[1].content").value(TEST_ARTICLE_REPORT_CONTENT)); } @DisplayName("ID로 개별 신고 조회를 요청하면 해당 신고를 반환한다.") @@ -122,7 +139,6 @@ void readArticleReportTest() throws Exception { andExpect(status().isOk()). andExpect(jsonPath("$.id").value(TEST_ARTICLE_REPORT_ID_1)). andExpect(jsonPath("$.content").value(TEST_ARTICLE_REPORT_CONTENT)). - andExpect(jsonPath("$.articleId").value(TEST_ARTICLE_ID)). andExpect(jsonPath("$.isFinished").value(false)); } diff --git a/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java index ec659693..ad4719f1 100644 --- a/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java +++ b/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java @@ -8,9 +8,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.ValueSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; import javax.transaction.Transactional; import java.time.LocalDateTime; @@ -19,6 +20,10 @@ import static org.assertj.core.api.Assertions.assertThat; +@ActiveProfiles("test") +@Sql("/truncate.sql") +@Transactional +@SpringBootTest public class ArticleReportRepositoryTest { @Autowired @@ -44,16 +49,16 @@ public class ArticleReportRepositoryTest { @BeforeEach @Transactional void setUp() { - reportCategory = new ReportCategory(3L, "분류3", "설명3"); + reportCategory = new ReportCategory(1L, "분류1", "설명1"); reportCategoryRepository.save(reportCategory); article = new Article("내용1", true); articleRepository.save(article); member = new Member(1L, "123456789", "naver", LocalDateTime.now(), false, Role.USER, new ArrayList<>()); memberRepository.save(member); - articleReport1 = new ArticleReport("신고 내용1", member, article, reportCategory); - articleReport2 = new ArticleReport("신고 내용2", member, article, reportCategory); - articleReport3 = new ArticleReport("신고 내용3", member, article, reportCategory); + articleReport1 = new ArticleReport(1L, "신고 내용1", member, article, reportCategory, LocalDateTime.now(), false); + articleReport2 = new ArticleReport(2L, "신고 내용2", member, article, reportCategory, LocalDateTime.now(), false); + articleReport3 = new ArticleReport(3L, "신고 내용3", member, article, reportCategory, LocalDateTime.now(), false); articleReportRepository.save(articleReport1); articleReportRepository.save(articleReport2); articleReportRepository.save(articleReport3); @@ -62,7 +67,7 @@ void setUp() { @DisplayName("게시글을 저장한다") @Test void saveTest() { - ArticleReport newArticleReport = new ArticleReport("신교 내용 4", member, article, reportCategory); + ArticleReport newArticleReport = new ArticleReport("신교 내용4", member, article, reportCategory); int articleReportSize = articleReportRepository.findAll().size(); articleReportRepository.save(newArticleReport); @@ -82,13 +87,12 @@ void findAllTest() { } @DisplayName("ID로 개별 ArticleReport를 조회한다") - @ValueSource(longs = {1L, 2L, 3L}) - @ParameterizedTest - void findByIdTest(Long id) { - ArticleReport articleReport = articleReportRepository.findById(id). - orElseThrow(() -> new ReportNotFoundException(id)); + void findByIdTest() { + ArticleReport articleReport = articleReportRepository.findById(1L). + orElseThrow(() -> new ReportNotFoundException(1L)); assertThat(articleReport).isNotNull(); - assertThat(articleReport.getId()).isEqualTo(id); + assertThat(articleReport.getId()).isEqualTo(1L); + assertThat(articleReport.getContent()).isEqualTo("신고 내용1"); } } diff --git a/src/test/java/com/saebyeok/saebyeok/domain/ArticleRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/ArticleRepositoryTest.java index 9265dd3a..f6422630 100644 --- a/src/test/java/com/saebyeok/saebyeok/domain/ArticleRepositoryTest.java +++ b/src/test/java/com/saebyeok/saebyeok/domain/ArticleRepositoryTest.java @@ -40,7 +40,6 @@ class ArticleRepositoryTest { @BeforeEach @Transactional void setUp() { - // TODO: 2020/08/12 emotion,sql 실행시킨 다음에, null 대신 진짜 값 넣어주면 어떨까? 고민 article1 = new Article("내용1", true); article2 = new Article("내용2", false); article3 = new Article("내용3", true); diff --git a/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java index 10de69e7..9af0322b 100644 --- a/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java +++ b/src/test/java/com/saebyeok/saebyeok/domain/ReportCategoryRepositoryTest.java @@ -29,6 +29,7 @@ public class ReportCategoryRepositoryTest { private ReportCategory reportCategory3; @BeforeEach + @Transactional void setUp() { reportCategory1 = new ReportCategory(1L, "분류1", "설명1"); reportCategory2 = new ReportCategory(2L, "분류2", "설명2"); diff --git a/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java b/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java index 07e077b4..7cadc7f9 100644 --- a/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java +++ b/src/test/java/com/saebyeok/saebyeok/service/ReportServiceTest.java @@ -1,13 +1,9 @@ package com.saebyeok.saebyeok.service; import com.saebyeok.saebyeok.domain.Article; -import com.saebyeok.saebyeok.domain.ArticleRepository; import com.saebyeok.saebyeok.domain.Member; import com.saebyeok.saebyeok.domain.Role; -import com.saebyeok.saebyeok.domain.report.ArticleReport; -import com.saebyeok.saebyeok.domain.report.ArticleReportRepository; -import com.saebyeok.saebyeok.domain.report.ReportCategory; -import com.saebyeok.saebyeok.domain.report.ReportCategoryRepository; +import com.saebyeok.saebyeok.domain.report.*; import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; import com.saebyeok.saebyeok.exception.ReportNotFoundException; @@ -49,11 +45,15 @@ public class ReportServiceTest { private ReportService reportService; @Mock - private ArticleRepository articleRepository; + private ArticleService articleService; + @Mock + private CommentService commentService; @Mock private ReportCategoryRepository reportCategoryRepository; @Mock private ArticleReportRepository articleReportRepository; + @Mock + private CommentReportRepository commentReportRepository; private ReportCategory reportCategory; private Member member; @@ -64,7 +64,7 @@ void setUp() { member = new Member(MEMBER_ID, MEMBER_OAUTH_ID, MEMBER_LOGIN_METHOD, LocalDateTime.now(), IS_DELETED, Role.USER, new ArrayList<>()); Article article = new Article(ARTICLE_ID, "게시물", member, LocalDateTime.now(), false, false, null, new ArrayList<>()); - reportService = new ReportService(articleRepository, reportCategoryRepository, articleReportRepository); + reportService = new ReportService(articleService, commentService, reportCategoryRepository, articleReportRepository, commentReportRepository); reportCategory = new ReportCategory(CATEGORY_ID, CATEGORY_NAME, CATEGORY_CONTENT); articleReport = new ArticleReport(ARTICLE_ID, ARTICLE_REPORT_CONTENT, member, article, reportCategory, LocalDateTime.now(), false); @@ -95,7 +95,6 @@ void getArticleReportsTest() { assertThat(articleReportResponses).hasSize(1); assertThat(articleReportResponses.get(0).getContent()).isEqualTo(ARTICLE_REPORT_CONTENT); - assertThat(articleReportResponses.get(0).getArticleId()).isEqualTo(ARTICLE_ID); assertThat(articleReportResponses.get(0).getIsFinished()).isEqualTo(false); } @@ -108,7 +107,6 @@ void readArticleReportTest() { assertThat(articleReportResponse).isNotNull(); assertThat(articleReportResponse.getContent()).isEqualTo(ARTICLE_REPORT_CONTENT); - assertThat(articleReportResponse.getArticleId()).isEqualTo(ARTICLE_ID); assertThat(articleReportResponse.getIsFinished()).isEqualTo(false); } From 76958589fcfab3b28df7322a25883c60ca478022 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Mon, 21 Sep 2020 23:50:02 +0900 Subject: [PATCH 09/33] =?UTF-8?q?test:=20CommentReportRepositoryTest=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1,=20admin=20=EC=84=A4=EC=A0=95=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20todo=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../saebyeok/controller/ReportController.java | 6 + .../domain/ArticleReportRepositoryTest.java | 19 ++-- .../domain/CommentReportRepositoryTest.java | 104 ++++++++++++++++++ 3 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java diff --git a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java index 0179e24e..23704f52 100644 --- a/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java +++ b/src/main/java/com/saebyeok/saebyeok/controller/ReportController.java @@ -37,6 +37,7 @@ public ResponseEntity createArticleReport(@LoginMember Member member, @Req @GetMapping("/reports/article") public ResponseEntity> getArticleReports(@LoginMember Member member) { + // TODO: 2020/09/21 admin 권한이 없다면 접근할 수 없도록 설정해야 함 List reportResponses = reportService.getArticleReports(member); return ResponseEntity.ok(reportResponses); @@ -44,6 +45,7 @@ public ResponseEntity> getArticleReports(@LoginMembe @GetMapping("/reports/article/{reportId}") public ResponseEntity readArticleReport(@LoginMember Member member, @PathVariable Long reportId) { + // TODO: 2020/09/21 admin 권한이 없다면 접근할 수 없도록 설정해야 함 ArticleReportResponse articleReportResponse = reportService.readArticleReport(member, reportId); return ResponseEntity.ok(articleReportResponse); @@ -51,6 +53,7 @@ public ResponseEntity readArticleReport(@LoginMember Memb @DeleteMapping("/reports/article/{reportId}") public ResponseEntity deleteArticleReport(@LoginMember Member member, @PathVariable Long reportId) { + // TODO: 2020/09/21 admin 권한이 없다면 접근할 수 없도록 설정해야 함 reportService.deleteArticleReport(member, reportId); return ResponseEntity.noContent().build(); @@ -67,6 +70,7 @@ public ResponseEntity createCommentReport(@LoginMember Member member, @Req @GetMapping("/reports/comment") public ResponseEntity> getCommentReports(@LoginMember Member member) { + // TODO: 2020/09/21 admin 권한이 없다면 접근할 수 없도록 설정해야 함 List reportResponses = reportService.getCommentReports(member); return ResponseEntity.ok(reportResponses); @@ -74,6 +78,7 @@ public ResponseEntity> getCommentReports(@LoginMembe @GetMapping("/reports/comment/{reportId}") public ResponseEntity readCommentReport(@LoginMember Member member, @PathVariable Long reportId) { + // TODO: 2020/09/21 admin 권한이 없다면 접근할 수 없도록 설정해야 함 CommentReportResponse commentReportResponse = reportService.readCommentReport(member, reportId); return ResponseEntity.ok(commentReportResponse); @@ -81,6 +86,7 @@ public ResponseEntity readCommentReport(@LoginMember Memb @DeleteMapping("/reports/comment/{reportId}") public ResponseEntity deleteCommentReport(@LoginMember Member member, @PathVariable Long reportId) { + // TODO: 2020/09/21 admin 권한이 없다면 접근할 수 없도록 설정해야 함 reportService.deleteCommentReport(member, reportId); return ResponseEntity.noContent().build(); diff --git a/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java index ad4719f1..03df39da 100644 --- a/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java +++ b/src/test/java/com/saebyeok/saebyeok/domain/ArticleReportRepositoryTest.java @@ -56,15 +56,15 @@ void setUp() { member = new Member(1L, "123456789", "naver", LocalDateTime.now(), false, Role.USER, new ArrayList<>()); memberRepository.save(member); - articleReport1 = new ArticleReport(1L, "신고 내용1", member, article, reportCategory, LocalDateTime.now(), false); - articleReport2 = new ArticleReport(2L, "신고 내용2", member, article, reportCategory, LocalDateTime.now(), false); - articleReport3 = new ArticleReport(3L, "신고 내용3", member, article, reportCategory, LocalDateTime.now(), false); + articleReport1 = new ArticleReport("신고 내용1", member, article, reportCategory); + articleReport2 = new ArticleReport("신고 내용2", member, article, reportCategory); + articleReport3 = new ArticleReport("신고 내용3", member, article, reportCategory); articleReportRepository.save(articleReport1); articleReportRepository.save(articleReport2); articleReportRepository.save(articleReport3); } - @DisplayName("게시글을 저장한다") + @DisplayName("게시글 신고를 저장한다") @Test void saveTest() { ArticleReport newArticleReport = new ArticleReport("신교 내용4", member, article, reportCategory); @@ -87,12 +87,15 @@ void findAllTest() { } @DisplayName("ID로 개별 ArticleReport를 조회한다") + @Test void findByIdTest() { - ArticleReport articleReport = articleReportRepository.findById(1L). - orElseThrow(() -> new ReportNotFoundException(1L)); + Long id = articleReport1.getId(); + ArticleReport articleReport = articleReportRepository.findById(id). + orElseThrow(() -> new ReportNotFoundException(id)); assertThat(articleReport).isNotNull(); - assertThat(articleReport.getId()).isEqualTo(1L); - assertThat(articleReport.getContent()).isEqualTo("신고 내용1"); + assertThat(articleReport.getId()).isEqualTo(id); + assertThat(articleReport.getContent()).isEqualTo(articleReport1.getContent()); + assertThat(articleReport.getIsFinished()).isEqualTo(articleReport1.getIsFinished()); } } diff --git a/src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java new file mode 100644 index 00000000..5cf793e1 --- /dev/null +++ b/src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java @@ -0,0 +1,104 @@ +package com.saebyeok.saebyeok.domain; + +import com.saebyeok.saebyeok.domain.report.CommentReport; +import com.saebyeok.saebyeok.domain.report.CommentReportRepository; +import com.saebyeok.saebyeok.domain.report.ReportCategory; +import com.saebyeok.saebyeok.domain.report.ReportCategoryRepository; +import com.saebyeok.saebyeok.exception.ReportNotFoundException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +import javax.transaction.Transactional; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@ActiveProfiles("test") +@Sql("/truncate.sql") +@Transactional +@SpringBootTest +public class CommentReportRepositoryTest { + // TODO: 2020/09/21 Documentation 작성 완료하기 + // TODO: 2020/09/21 CommentRepo TEst, ARticleRepo TEst + // TODO: 2020/09/21 admin/ check를 통한 get의 권한 관리, deelete! + + @Autowired + private CommentReportRepository commentReportRepository; + + @Autowired + private MemberRepository memberRepository; + + @Autowired + private CommentRepository commentRepository; + + @Autowired + private ReportCategoryRepository reportCategoryRepository; + + private Comment comment; + private Member member; + private ReportCategory reportCategory; + + private CommentReport commentReport1; + private CommentReport commentReport2; + private CommentReport commentReport3; + + @BeforeEach + @Transactional + void setUp() { + reportCategory = new ReportCategory(1L, "분류1", "설명1"); + reportCategoryRepository.save(reportCategory); + comment = new Comment("HI", "nickName"); + commentRepository.save(comment); + member = new Member(1L, "123456789", "naver", LocalDateTime.now(), false, Role.USER, new ArrayList<>()); + memberRepository.save(member); + + commentReport1 = new CommentReport("신고 내용1", member, comment, reportCategory); + commentReport2 = new CommentReport("신고 내용2", member, comment, reportCategory); + commentReport3 = new CommentReport("신고 내용3", member, comment, reportCategory); + commentReportRepository.save(commentReport1); + commentReportRepository.save(commentReport2); + commentReportRepository.save(commentReport3); + } + + @DisplayName("댓글 신고를 저장한다") + @Test + void saveTest() { + CommentReport newCommentReport = new CommentReport("신고 내용4", member, comment, reportCategory); + int commentReportSize = commentReportRepository.findAll().size(); + + commentReportRepository.save(newCommentReport); + + List commentReports = commentReportRepository.findAll(); + assertThat(commentReports).hasSize(commentReportSize + 1).contains(newCommentReport); + } + + @DisplayName("전체 CommentReport를 조회한다.") + @Test + void findAllTest() { + List commentReports = commentReportRepository.findAll(); + assertThat(commentReports). + hasSize(3). + extracting("content"). + containsOnly(commentReport1.getContent(), commentReport2.getContent(), commentReport3.getContent()); + } + + @DisplayName("ID로 개별 CommentReport를 조회한다") + @Test + void findByIdTest() { + Long id = commentReport1.getId(); + CommentReport commentReport = commentReportRepository.findById(id). + orElseThrow(() -> new ReportNotFoundException(id)); + + assertThat(commentReport).isNotNull(); + assertThat(commentReport.getId()).isEqualTo(id); + assertThat(commentReport.getContent()).isEqualTo(commentReport1.getContent()); + assertThat(commentReport.getIsFinished()).isEqualTo(commentReport1.getIsFinished()); + } +} From 14d76c4c15159a72684cb87c2ebc7a83df7f37a4 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Tue, 22 Sep 2020 13:15:43 +0900 Subject: [PATCH 10/33] =?UTF-8?q?feat:=20ArticleReport=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=AC=B8=EC=84=9C=ED=99=94=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api-docs.adoc | 20 +++ .../documentation/ReportDocumentation.java | 169 +++++++++++++++++- .../domain/CommentReportRepositoryTest.java | 4 - 3 files changed, 183 insertions(+), 10 deletions(-) diff --git a/src/docs/asciidoc/api-docs.adoc b/src/docs/asciidoc/api-docs.adoc index efc59ccf..8a175a13 100644 --- a/src/docs/asciidoc/api-docs.adoc +++ b/src/docs/asciidoc/api-docs.adoc @@ -92,3 +92,23 @@ operation::analysis/comments[snippets='http-request,http-response,request-header === 신고 분류 전체 조회 operation::reports/categories[snippets='http-request,http-response,request-headers,response-fields'] + +[[resources-reports-article-create]] +=== 게시물 신고 생성 + +operation::reports/article/create[snippets='http-request,http-response,request-headers,request-fields,response-headers'] + +[[resources-reports-article-get]] +=== 게시물 신고 전체 조회 + +operation::reports/article/get[snippets='http-request,http-response,request-headers,response-fields'] + +[[resources-reports-article-read]] +=== 게시물 신고 조회 + +operation::reports/article/read[snippets='http-request,http-response,request-headers,path-parameters,response-fields'] + +[[resources-reports-article-delete]] +=== 게시물 신고 삭제 + +operation::reports/article/delete[snippets='http-request,http-response,path-parameters,request-headers'] \ No newline at end of file diff --git a/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java b/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java index 9146c7e1..453cfeb6 100644 --- a/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java +++ b/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java @@ -2,7 +2,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.saebyeok.saebyeok.documentation.common.Documentation; -import com.saebyeok.saebyeok.dto.TokenResponse; +import com.saebyeok.saebyeok.domain.Member; +import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.domain.report.ReportCategory; +import com.saebyeok.saebyeok.dto.*; +import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; +import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; import com.saebyeok.saebyeok.service.report.ReportService; import org.junit.jupiter.api.BeforeEach; @@ -18,17 +23,19 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; -import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.headers.HeaderDocumentation.*; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -79,4 +86,154 @@ void getReportCategories() throws Exception { ) )); } + + @Test + void createArticleReport() throws Exception { + ArticleReportCreateRequest articleReportCreateRequest = new ArticleReportCreateRequest("게시물 신고 내용", 1L, 1L); + ArticleReport articleReport = new ArticleReport(1L, "게시물 신고 내용", null, null, null, LocalDateTime.now(), false); + + given(reportService.createArticleReport(any(Member.class), any())).willReturn(articleReport); + + String content = objectMapper.writeValueAsString(articleReportCreateRequest); + + this.mockMvc.perform(post("/api/reports/article"). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON). + content(content). + contentType(MediaType.APPLICATION_JSON)). + andExpect(status().isCreated()). + andDo(print()). + andDo(document("reports/article/create", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials") + ), + requestFields( + fieldWithPath("content").type(JsonFieldType.STRING).description("게시물 신고 내용"), + fieldWithPath("articleId").type(JsonFieldType.NUMBER).description("신고할 게시물의 ID"), + fieldWithPath("reportCategoryId").type(JsonFieldType.NUMBER).description("신고의 분류 ID")), + responseHeaders( + headerWithName("Location").description("생성 성공 시 해당 주소로 이동") + ) + )); + } + + @Test + void getArticleReports() throws Exception { + ArticleReport articleReport = new ArticleReport(1L, "게시물 신고 내용", null, null, new ReportCategory(1L, "신고 분류 이름", "신고 분류 상세 내용"), LocalDateTime.now(), false); + + List comments = Arrays.asList(new CommentResponse(1L, "댓글1", "닉네임1", false, + LocalDateTime.now(), true, 10L, false)); + EmotionResponse emotionResponse = new EmotionResponse(1L, "기뻐요", "이미지 리소스 링크"); + List subEmotionResponses = Arrays.asList(new SubEmotionResponse(1L, "행복해요"), new SubEmotionResponse(2L, "설레요")); + ArticleResponse articleResponse = new ArticleResponse(1L, "내용", LocalDateTime.now(), emotionResponse, subEmotionResponses, true, true, 10L, false, comments); + + List articleReportResponses = Arrays.asList(new ArticleReportResponse(articleReport, articleResponse)); + + given(reportService.getArticleReports(any(Member.class))).willReturn(articleReportResponses); + + this.mockMvc.perform(get("/api/reports/article"). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON)). + andExpect(status().isOk()). + andDo(print()). + andDo(document("reports/article/get", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials") + ), + responseFields( + fieldWithPath("[]").type(JsonFieldType.ARRAY).description("전체 게시물 신고의 목록"), + fieldWithPath("[].id").type(JsonFieldType.NUMBER).description("게시물 신고의 ID"), + fieldWithPath("[].content").type(JsonFieldType.STRING).description("게시물 신고의 내용"), + fieldWithPath("[].article").type(JsonFieldType.OBJECT).description("신고된 게시물"), + fieldWithPath("[].reportCategory").type(JsonFieldType.OBJECT).description("신고의 분류"), + fieldWithPath("[].isFinished").type(JsonFieldType.BOOLEAN).description("신고의 완료 여부"), + fieldWithPath("[].article.id").type(JsonFieldType.NUMBER).description("신고된 게시물의 ID"), + fieldWithPath("[].article.content").type(JsonFieldType.STRING).description("신고된 게시물의 내용"), + fieldWithPath("[].article.createdDate").type(JsonFieldType.STRING).description("신고된 게시물의 작성 시간"), + subsectionWithPath("[].article.emotion").type(JsonFieldType.OBJECT).description("신고된 게시물의 감정 대분류"), + subsectionWithPath("[].article.subEmotions[]").type(JsonFieldType.ARRAY).description("신고된 게시글의 감정 소분류 목록"), + fieldWithPath("[].article.isCommentAllowed").type(JsonFieldType.BOOLEAN).description("신고된 게시글의 댓글 허용 여부"), + fieldWithPath("[].article.isMine").type(JsonFieldType.BOOLEAN).description("신고된 게시글이 내가 쓴 글인지 여부"), + fieldWithPath("[].article.likesCount").type(JsonFieldType.NUMBER).description("신고된 게시글이 받은 공감의 수"), + fieldWithPath("[].article.isLikedByMe").type(JsonFieldType.BOOLEAN).description("신고된 게시글을 내가 공감한 상태인지 여부"), + subsectionWithPath("[].article.comments[]").type(JsonFieldType.ARRAY).description("신고된 게시물의 댓글 목록"), + fieldWithPath("[].reportCategory.id").type(JsonFieldType.NUMBER).description("신고 분류의 ID"), + fieldWithPath("[].reportCategory.name").type(JsonFieldType.STRING).description("신고 분류의 이름"), + fieldWithPath("[].reportCategory.content").type(JsonFieldType.STRING).description("신고 분류의 상세 설명") + ) + )); + } + + @Test + void readArticleReports() throws Exception { + ArticleReport articleReport = new ArticleReport(1L, "게시물 신고 내용", null, null, new ReportCategory(1L, "신고 분류 이름", "신고 분류 상세 내용"), LocalDateTime.now(), false); + + List comments = Arrays.asList(new CommentResponse(1L, "댓글1", "닉네임1", false, + LocalDateTime.now(), true, 10L, false)); + EmotionResponse emotionResponse = new EmotionResponse(1L, "기뻐요", "이미지 리소스 링크"); + List subEmotionResponses = Arrays.asList(new SubEmotionResponse(1L, "행복해요"), new SubEmotionResponse(2L, "설레요")); + ArticleResponse articleResponse = new ArticleResponse(1L, "내용", LocalDateTime.now(), emotionResponse, subEmotionResponses, true, true, 10L, false, comments); + + ArticleReportResponse articleReportResponse = new ArticleReportResponse(articleReport, articleResponse); + + given(reportService.readArticleReport(any(Member.class), any())).willReturn(articleReportResponse); + + this.mockMvc.perform(get("/api/reports/article/{reportId}", 1L). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON)). + andExpect(status().isOk()). + andDo(print()). + andDo(document("reports/article/read", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials") + ), + pathParameters( + parameterWithName("reportId").description("삭제할 게시물 신고의 게시물 ID") + ), + responseFields( + fieldWithPath("id").type(JsonFieldType.NUMBER).description("게시물 신고의 ID"), + fieldWithPath("content").type(JsonFieldType.STRING).description("게시물 신고의 내용"), + fieldWithPath("article").type(JsonFieldType.OBJECT).description("신고된 게시물"), + fieldWithPath("reportCategory").type(JsonFieldType.OBJECT).description("신고의 분류"), + fieldWithPath("isFinished").type(JsonFieldType.BOOLEAN).description("신고의 완료 여부"), + fieldWithPath("article.id").type(JsonFieldType.NUMBER).description("신고된 게시물의 ID"), + fieldWithPath("article.content").type(JsonFieldType.STRING).description("신고된 게시물의 내용"), + fieldWithPath("article.createdDate").type(JsonFieldType.STRING).description("신고된 게시물의 작성 시간"), + subsectionWithPath("article.emotion").type(JsonFieldType.OBJECT).description("신고된 게시물의 감정 대분류"), + subsectionWithPath("article.subEmotions[]").type(JsonFieldType.ARRAY).description("신고된 게시글의 감정 소분류 목록"), + fieldWithPath("article.isCommentAllowed").type(JsonFieldType.BOOLEAN).description("신고된 게시글의 댓글 허용 여부"), + fieldWithPath("article.isMine").type(JsonFieldType.BOOLEAN).description("신고된 게시글이 내가 쓴 글인지 여부"), + fieldWithPath("article.likesCount").type(JsonFieldType.NUMBER).description("신고된 게시글이 받은 공감의 수"), + fieldWithPath("article.isLikedByMe").type(JsonFieldType.BOOLEAN).description("신고된 게시글을 내가 공감한 상태인지 여부"), + subsectionWithPath("article.comments[]").type(JsonFieldType.ARRAY).description("신고된 게시물의 댓글 목록"), + fieldWithPath("reportCategory.id").type(JsonFieldType.NUMBER).description("신고 분류의 ID"), + fieldWithPath("reportCategory.name").type(JsonFieldType.STRING).description("신고 분류의 이름"), + fieldWithPath("reportCategory.content").type(JsonFieldType.STRING).description("신고 분류의 상세 설명") + ) + )); + } + + @Test + void deleteArticleReport() throws Exception { + this.mockMvc.perform(delete("/api/reports/article/{reportId}", 1L). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON)). + andExpect(status().isNoContent()). + andDo(print()). + andDo(document("reports/article/delete", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials")), + pathParameters( + parameterWithName("reportId").description("삭제할 게시물 신고의 게시물 ID") + )) + ); + } } diff --git a/src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java b/src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java index 5cf793e1..7bcb1f37 100644 --- a/src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java +++ b/src/test/java/com/saebyeok/saebyeok/domain/CommentReportRepositoryTest.java @@ -25,10 +25,6 @@ @Transactional @SpringBootTest public class CommentReportRepositoryTest { - // TODO: 2020/09/21 Documentation 작성 완료하기 - // TODO: 2020/09/21 CommentRepo TEst, ARticleRepo TEst - // TODO: 2020/09/21 admin/ check를 통한 get의 권한 관리, deelete! - @Autowired private CommentReportRepository commentReportRepository; From 800aa2e881e18e155244a01df3e84885031e0e57 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Tue, 22 Sep 2020 13:31:27 +0900 Subject: [PATCH 11/33] =?UTF-8?q?feat:=20CommentReport=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=AC=B8=EC=84=9C=ED=99=94=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api-docs.adoc | 28 +++- .../dto/report/CommentReportResponse.java | 4 +- .../documentation/ReportDocumentation.java | 146 +++++++++++++++++- 3 files changed, 172 insertions(+), 6 deletions(-) diff --git a/src/docs/asciidoc/api-docs.adoc b/src/docs/asciidoc/api-docs.adoc index 8a175a13..3bc5cd2a 100644 --- a/src/docs/asciidoc/api-docs.adoc +++ b/src/docs/asciidoc/api-docs.adoc @@ -93,6 +93,9 @@ operation::analysis/comments[snippets='http-request,http-response,request-header operation::reports/categories[snippets='http-request,http-response,request-headers,response-fields'] +[[resources-reports-article]] +== ArticleReports + [[resources-reports-article-create]] === 게시물 신고 생성 @@ -111,4 +114,27 @@ operation::reports/article/read[snippets='http-request,http-response,request-hea [[resources-reports-article-delete]] === 게시물 신고 삭제 -operation::reports/article/delete[snippets='http-request,http-response,path-parameters,request-headers'] \ No newline at end of file +operation::reports/article/delete[snippets='http-request,http-response,path-parameters,request-headers'] + +[[resources-reports-comment]] +== CommentReports + +[[resources-reports-comment-create]] +=== 댓글 신고 생성 + +operation::reports/comment/create[snippets='http-request,http-response,request-headers,request-fields,response-headers'] + +[[resources-reports-comment-get]] +=== 댓글 신고 전체 조회 + +operation::reports/comment/get[snippets='http-request,http-response,request-headers,response-fields'] + +[[resources-reports-comment-read]] +=== 댓글 신고 조회 + +operation::reports/comment/read[snippets='http-request,http-response,request-headers,path-parameters,response-fields'] + +[[resources-reports-comment-delete]] +=== 댓글 신고 삭제 + +operation::reports/comment/delete[snippets='http-request,http-response,path-parameters,request-headers'] \ No newline at end of file diff --git a/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java b/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java index 1433ac69..a89ce7db 100644 --- a/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java +++ b/src/main/java/com/saebyeok/saebyeok/dto/report/CommentReportResponse.java @@ -13,14 +13,14 @@ public class CommentReportResponse { private Long id; private String content; private CommentResponse comment; - private ReportCategoryResponse reportCategoryResponse; + private ReportCategoryResponse reportCategory; private Boolean isFinished; public CommentReportResponse(CommentReport commentReport, CommentResponse commentResponse) { this.id = commentReport.getId(); this.content = commentReport.getContent(); this.comment = commentResponse; - this.reportCategoryResponse = new ReportCategoryResponse(commentReport.getReportCategory()); + this.reportCategory = new ReportCategoryResponse(commentReport.getReportCategory()); this.isFinished = commentReport.getIsFinished(); } } diff --git a/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java b/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java index 453cfeb6..04bae98c 100644 --- a/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java +++ b/src/test/java/com/saebyeok/saebyeok/documentation/ReportDocumentation.java @@ -2,13 +2,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.saebyeok.saebyeok.documentation.common.Documentation; +import com.saebyeok.saebyeok.domain.Comment; import com.saebyeok.saebyeok.domain.Member; import com.saebyeok.saebyeok.domain.report.ArticleReport; +import com.saebyeok.saebyeok.domain.report.CommentReport; import com.saebyeok.saebyeok.domain.report.ReportCategory; import com.saebyeok.saebyeok.dto.*; -import com.saebyeok.saebyeok.dto.report.ArticleReportCreateRequest; -import com.saebyeok.saebyeok.dto.report.ArticleReportResponse; -import com.saebyeok.saebyeok.dto.report.ReportCategoryResponse; +import com.saebyeok.saebyeok.dto.report.*; import com.saebyeok.saebyeok.service.report.ReportService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,6 +24,7 @@ import org.springframework.web.context.WebApplicationContext; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -236,4 +237,143 @@ void deleteArticleReport() throws Exception { )) ); } + + + @Test + void createCommentReport() throws Exception { + CommentReportCreateRequest commentReportCreateRequest = new CommentReportCreateRequest("댓글 신고 내용", 1L, 1L); + CommentReport commentReport = new CommentReport(1L, "댓글 신고 내용", null, null, null, LocalDateTime.now(), false); + + given(reportService.createCommentReport(any(Member.class), any())).willReturn(commentReport); + + String content = objectMapper.writeValueAsString(commentReportCreateRequest); + + this.mockMvc.perform(post("/api/reports/comment"). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON). + content(content). + contentType(MediaType.APPLICATION_JSON)). + andExpect(status().isCreated()). + andDo(print()). + andDo(document("reports/comment/create", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials") + ), + requestFields( + fieldWithPath("content").type(JsonFieldType.STRING).description("댓글 신고 내용"), + fieldWithPath("commentId").type(JsonFieldType.NUMBER).description("신고할 댓글의 ID"), + fieldWithPath("reportCategoryId").type(JsonFieldType.NUMBER).description("신고의 분류 ID")), + responseHeaders( + headerWithName("Location").description("생성 성공 시 해당 주소로 이동") + ) + )); + } + + @Test + void getCommentReports() throws Exception { + CommentReport commentReport = new CommentReport(1L, "댓글 신고 내용", null, null, new ReportCategory(1L, "신고 분류 이름", "신고 분류 상세 내용"), LocalDateTime.now(), false); + Comment comment = new Comment(1L, "댓글 내용", new Member(), "댓글 닉네임", LocalDateTime.now(), null, false, new ArrayList<>()); + CommentResponse commentResponse = new CommentResponse(comment, new Member()); + + List commentReportResponses = Arrays.asList(new CommentReportResponse(commentReport, commentResponse)); + + given(reportService.getCommentReports(any(Member.class))).willReturn(commentReportResponses); + + this.mockMvc.perform(get("/api/reports/comment"). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON)). + andExpect(status().isOk()). + andDo(print()). + andDo(document("reports/comment/get", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials") + ), + responseFields( + fieldWithPath("[]").type(JsonFieldType.ARRAY).description("전체 댓글 신고의 목록"), + fieldWithPath("[].id").type(JsonFieldType.NUMBER).description("댓글 신고의 ID"), + fieldWithPath("[].content").type(JsonFieldType.STRING).description("댓글 신고의 내용"), + fieldWithPath("[].comment").type(JsonFieldType.OBJECT).description("신고된 댓글"), + fieldWithPath("[].reportCategory").type(JsonFieldType.OBJECT).description("신고의 분류"), + fieldWithPath("[].isFinished").type(JsonFieldType.BOOLEAN).description("신고의 완료 여부"), + fieldWithPath("[].comment.id").type(JsonFieldType.NUMBER).description("신고된 댓글의 ID"), + fieldWithPath("[].comment.content").type(JsonFieldType.STRING).description("신고된 댓글의 내용"), + fieldWithPath("[].comment.nickname").type(JsonFieldType.STRING).description("신고된 댓글의 닉네임"), + fieldWithPath("[].comment.isDeleted").type(JsonFieldType.BOOLEAN).description("신고된 댓글의 삭제 여부"), + fieldWithPath("[].comment.createdDate").type(JsonFieldType.STRING).description("신고된 댓글의 작성 시간"), + fieldWithPath("[].comment.isMine").type(JsonFieldType.BOOLEAN).description("신고된 댓글이 내가 쓴 댓글인지 여부"), + fieldWithPath("[].comment.likesCount").type(JsonFieldType.NUMBER).description("신고된 댓글이 받은 공감의 수"), + fieldWithPath("[].comment.isLikedByMe").type(JsonFieldType.BOOLEAN).description("신고된 댓글을 내가 공감한 상태인지 여부"), + fieldWithPath("[].reportCategory.id").type(JsonFieldType.NUMBER).description("신고 분류의 ID"), + fieldWithPath("[].reportCategory.name").type(JsonFieldType.STRING).description("신고 분류의 이름"), + fieldWithPath("[].reportCategory.content").type(JsonFieldType.STRING).description("신고 분류의 상세 설명") + ) + )); + } + + @Test + void readCommentReports() throws Exception { + CommentReport commentReport = new CommentReport(1L, "댓글 신고 내용", null, null, new ReportCategory(1L, "신고 분류 이름", "신고 분류 상세 내용"), LocalDateTime.now(), false); + Comment comment = new Comment(1L, "댓글 내용", new Member(), "댓글 닉네임", LocalDateTime.now(), null, false, new ArrayList<>()); + CommentResponse commentResponse = new CommentResponse(comment, new Member()); + + CommentReportResponse commentReportResponse = new CommentReportResponse(commentReport, commentResponse); + + given(reportService.readCommentReport(any(Member.class), any())).willReturn(commentReportResponse); + + this.mockMvc.perform(get("/api/reports/comment/{reportId}", 1L). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON)). + andExpect(status().isOk()). + andDo(print()). + andDo(document("reports/comment/read", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials") + ), + pathParameters( + parameterWithName("reportId").description("삭제할 댓글 신고의 댓글 ID") + ), + responseFields( + fieldWithPath("id").type(JsonFieldType.NUMBER).description("댓글 신고의 ID"), + fieldWithPath("content").type(JsonFieldType.STRING).description("댓글 신고의 내용"), + fieldWithPath("comment").type(JsonFieldType.OBJECT).description("신고된 댓글"), + fieldWithPath("reportCategory").type(JsonFieldType.OBJECT).description("신고의 분류"), + fieldWithPath("isFinished").type(JsonFieldType.BOOLEAN).description("신고의 완료 여부"), + fieldWithPath("comment.id").type(JsonFieldType.NUMBER).description("신고된 댓글의 ID"), + fieldWithPath("comment.content").type(JsonFieldType.STRING).description("신고된 댓글의 내용"), + fieldWithPath("comment.nickname").type(JsonFieldType.STRING).description("신고된 댓글의 닉네임"), + fieldWithPath("comment.isDeleted").type(JsonFieldType.BOOLEAN).description("신고된 댓글의 삭제 여부"), + fieldWithPath("comment.createdDate").type(JsonFieldType.STRING).description("신고된 댓글의 작성 시간"), + fieldWithPath("comment.isMine").type(JsonFieldType.BOOLEAN).description("신고된 댓글이 내가 쓴 댓글인지 여부"), + fieldWithPath("comment.likesCount").type(JsonFieldType.NUMBER).description("신고된 댓글이 받은 공감의 수"), + fieldWithPath("comment.isLikedByMe").type(JsonFieldType.BOOLEAN).description("신고된 댓글을 내가 공감한 상태인지 여부"), + fieldWithPath("reportCategory.id").type(JsonFieldType.NUMBER).description("신고 분류의 ID"), + fieldWithPath("reportCategory.name").type(JsonFieldType.STRING).description("신고 분류의 이름"), + fieldWithPath("reportCategory.content").type(JsonFieldType.STRING).description("신고 분류의 상세 설명") + ) + )); + } + + @Test + void deleteCommentReport() throws Exception { + this.mockMvc.perform(delete("/api/reports/comment/{reportId}", 1L). + header("Authorization", tokenResponse.getTokenType() + " " + tokenResponse.getAccessToken()). + accept(MediaType.APPLICATION_JSON)). + andExpect(status().isNoContent()). + andDo(print()). + andDo(document("reports/comment/delete", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders( + headerWithName("Authorization").description("Bearer auth credentials")), + pathParameters( + parameterWithName("reportId").description("삭제할 댓글 신고의 댓글 ID") + )) + ); + } } From 876af2318c1cc978af1509d2fe16b5666493d657 Mon Sep 17 00:00:00 2001 From: gunhee lee Date: Tue, 22 Sep 2020 14:28:41 +0900 Subject: [PATCH 12/33] =?UTF-8?q?feat:=20=EC=8B=A0=EA=B3=A0=20=EC=A0=91?= =?UTF-8?q?=EC=88=98=20=EA=B8=B0=EB=8A=A5=20=ED=94=84=EB=A1=A0=ED=8A=B8?= =?UTF-8?q?=EC=97=94=EB=93=9C=EC=97=90=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - api, vuex 모듈에 댓글 신고와 게시글 신고 기능 추가 - ReportButton.vue에 신고 로직 추가. 댓글인지 게시글인지에 따라 swtich로 분리되며, 각각의 메서드에서 CreateRequest를 만들어 생성 요청을 보낸다. 이후 링크되는 곳이 없어, 이에 대한 처리 대신 초기화 처리만 진행하였다. --- src/frontend/src/api/modules/report.js | 30 ++++++++---- src/frontend/src/components/ReportButton.vue | 51 ++++++++++++++++++-- src/frontend/src/store/modules/report.js | 16 +++++- src/frontend/src/store/shared/actionTypes.js | 2 + 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/src/frontend/src/api/modules/report.js b/src/frontend/src/api/modules/report.js index 23fb8539..82aefeb4 100644 --- a/src/frontend/src/api/modules/report.js +++ b/src/frontend/src/api/modules/report.js @@ -4,19 +4,31 @@ const BASE_URL = '/reports'; const ReportService = { getCategories() { - return ApiService.get(`/reports/categories`); + return ApiService.get(`${BASE_URL}/categories`); }, - create(report) { - return ApiService.post(`${BASE_URL}`, report); + createArticleReport(report) { + return ApiService.post(`${BASE_URL}/article`, report); }, - get(reportId) { - return ApiService.get(`${BASE_URL}/${reportId}`); + getArticleReport(reportId) { + return ApiService.get(`${BASE_URL}/artcile/${reportId}`); }, - getAll(params) { - return ApiService.getWithParams(`${BASE_URL}`, params); + getArticleReports() { + return ApiService.get(`${BASE_URL}/article`); }, - delete(reportId) { - return ApiService.delete(`${BASE_URL}/${reportId}`); + deleteArticleReport(reportId) { + return ApiService.delete(`${BASE_URL}/article/${reportId}`); + }, + createCommentReport(report) { + return ApiService.post(`${BASE_URL}/comment`, report); + }, + getCommentReport(reportId) { + return ApiService.get(`${BASE_URL}/comment/${reportId}`); + }, + getCommentReports() { + return ApiService.get(`${BASE_URL}/comment`); + }, + deleteCommentReport(reportId) { + return ApiService.delete(`${BASE_URL}/comment/${reportId}`); } }; diff --git a/src/frontend/src/components/ReportButton.vue b/src/frontend/src/components/ReportButton.vue index 92be9f78..27fd4f8d 100644 --- a/src/frontend/src/components/ReportButton.vue +++ b/src/frontend/src/components/ReportButton.vue @@ -74,7 +74,11 @@