diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02bd405a..771ad5d7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: run: chmod +x ./gradlew - name: Build and Test with Gradle - run: ./gradlew bootJar -Pprofile=dev + run: ./gradlew bootJar -Pprofile=dev --info diff --git a/build.gradle b/build.gradle index 1ac7b2e5..a210ad53 100644 --- a/build.gradle +++ b/build.gradle @@ -89,6 +89,9 @@ dependencies { implementation 'org.opensearch.client:spring-data-opensearch:1.3.0' implementation 'org.opensearch.client:opensearch-java:2.9.1' + // mybatis + implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.4' + compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' diff --git a/src/docs/asciidoc/api/mypage/comment-get.adoc b/src/docs/asciidoc/api/mypage/comment-get.adoc new file mode 100644 index 00000000..e8cf4d6e --- /dev/null +++ b/src/docs/asciidoc/api/mypage/comment-get.adoc @@ -0,0 +1,37 @@ +[[Comment-Get]] +== 내가 썼어요 댓글/답글 조회 API(GET: /devdevdev/api/v1/mypage/comments) + +* 회원이 작성한 댓글/답글을 조회한다. +* 최초 요청시 pickCommentId, techCommentId 는 가장 큰 숫자 값을 요청해야 합니다. + +=== 정상 요청/응답 + +==== HTTP Request + +include::{snippets}/mypage-comments/http-request.adoc[] + +==== HTTP Request Header Fields + +include::{snippets}/mypage-comments/request-headers.adoc[] + +==== HTTP Request Query Parameters Fields + +include::{snippets}/mypage-comments/query-parameters.adoc[] + +==== HTTP Response + +include::{snippets}/mypage-comments/http-response.adoc[] + +==== HTTP Response Fields + +include::{snippets}/mypage-comments/response-fields.adoc[] + +=== 예외 + +==== HTTP Response + +* `익명 회원은 사용할 수 없는 기능 입니다.`: 익명 회원인 경우 +* `회원을 찾을 수 없습니다.`: 회원이 존재하지 않는 경우 +* `유효하지 않은 회원 입니다.`: 회원이 유효하지 않은 경우 + +include::{snippets}/mypage-comments-member-exception/response-body.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/api/mypage/mypage.adoc b/src/docs/asciidoc/api/mypage/mypage.adoc index 62cd90fb..d4b198dc 100644 --- a/src/docs/asciidoc/api/mypage/mypage.adoc +++ b/src/docs/asciidoc/api/mypage/mypage.adoc @@ -5,3 +5,4 @@ include::mypick-main.adoc[] include::exit-member.adoc[] include::exit-survey.adoc[] include::record-exit-survey.adoc[] +include::comment-get.adoc[] diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/Pick.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/Pick.java index d32510dc..85e69df7 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/Pick.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/Pick.java @@ -88,7 +88,7 @@ public class Pick extends BasicTime { private List embeddings; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id") + @JoinColumn(name = "member_id", nullable = false) private Member member; @OneToMany(mappedBy = "pick") diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/TechArticle.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/TechArticle.java index ae50a99a..9b49e445 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/TechArticle.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/entity/TechArticle.java @@ -1,6 +1,7 @@ package com.dreamypatisiel.devdevdev.domain.entity; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.policy.TechArticlePopularScorePolicy; import com.dreamypatisiel.devdevdev.elastic.domain.document.ElasticTechArticle; @@ -35,6 +36,8 @@ public class TechArticle extends BasicTime { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private Title title; + @Embedded @AttributeOverride(name = "count", column = @Column(name = "view_total_count") @@ -79,8 +82,10 @@ public class TechArticle extends BasicTime { private List recommends = new ArrayList<>(); @Builder - private TechArticle(Count viewTotalCount, Count recommendTotalCount, Count commentTotalCount, Count popularScore, + private TechArticle(Title title, Count viewTotalCount, Count recommendTotalCount, Count commentTotalCount, + Count popularScore, Url techArticleUrl, Company company, String elasticId) { + this.title = title; this.techArticleUrl = techArticleUrl; this.viewTotalCount = viewTotalCount; this.recommendTotalCount = recommendTotalCount; @@ -92,6 +97,7 @@ private TechArticle(Count viewTotalCount, Count recommendTotalCount, Count comme public static TechArticle createTechArticle(ElasticTechArticle elasticTechArticle, Company company) { TechArticle techArticle = TechArticle.builder() + .title(new Title(elasticTechArticle.getTitle())) .techArticleUrl(new Url(elasticTechArticle.getTechArticleUrl())) .viewTotalCount(new Count(elasticTechArticle.getViewTotalCount())) .recommendTotalCount(new Count(elasticTechArticle.getRecommendTotalCount())) @@ -105,10 +111,11 @@ public static TechArticle createTechArticle(ElasticTechArticle elasticTechArticl return techArticle; } - public static TechArticle createTechArticle(Url techArticleUrl, Count viewTotalCount, Count recommendTotalCount, - Count commentTotalCount, - Count popularScore, String elasticId, Company company) { + public static TechArticle createTechArticle(Title title, Url techArticleUrl, Count viewTotalCount, + Count recommendTotalCount, Count commentTotalCount, Count popularScore, + String elasticId, Company company) { return TechArticle.builder() + .title(title) .techArticleUrl(techArticleUrl) .viewTotalCount(viewTotalCount) .recommendTotalCount(recommendTotalCount) diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/CommentRepository.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/CommentRepository.java new file mode 100644 index 00000000..bf34f2b6 --- /dev/null +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/CommentRepository.java @@ -0,0 +1,61 @@ +package com.dreamypatisiel.devdevdev.domain.repository.comment; + +import com.dreamypatisiel.devdevdev.domain.repository.comment.mybatis.CommentMapper; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentRepository; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechCommentRepository; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentFilter; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class CommentRepository { + + private final CommentMapper commentMapper; + private final PickCommentRepository pickCommentRepository; + private final TechCommentRepository techCommentRepository; + + public SliceCustom findMyWrittenCommentsByCursor(Long memberId, + Long pickCommentId, + Long techCommentId, + MyWrittenCommentFilter myWrittenCommentSort, + Pageable pageable) { + + // 픽픽픽 + if (MyWrittenCommentFilter.PICK.equals(myWrittenCommentSort)) { + return pickCommentRepository.findMyWrittenPickCommentsByCursor(memberId, pickCommentId, pageable); + } + + // 기술블로그 + if (MyWrittenCommentFilter.TECH_ARTICLE.equals(myWrittenCommentSort)) { + return techCommentRepository.findMyWrittenTechCommentsByCursor(memberId, techCommentId, pageable); + } + + // 전체 + // 회원이 작성한 픽픽픽, 기술블로그 댓글 조회 + List findMyWrittenComments = commentMapper.findByMemberIdAndPickCommentIdAndTechCommentIdOrderByCommentCreatedAtDesc( + memberId, pickCommentId, techCommentId, pageable.getPageSize()); + + // 다음 페이지 존재 여부 + boolean hasNext = findMyWrittenComments.size() >= pageable.getPageSize(); + + // 회원이 작성한 댓글 총 갯수(삭제 미포함) + Long commentTotalCount = countByCreatedByIdAndDeletedAtIsNull(memberId); + + return new SliceCustom<>(findMyWrittenComments, pageable, hasNext, commentTotalCount); + } + + private Long countByCreatedByIdAndDeletedAtIsNull(Long createdById) { + + // 회원이 작성한 픽픽픽 댓글 갯수(삭제 미포함) + Long pickCommentTotal = pickCommentRepository.countByCreatedByIdAndDeletedAtIsNull(createdById); + + // 회원이 작성한 기술블로그 댓글 갯수(삭제 미포함) + Long techCommentTotal = techCommentRepository.countByCreatedByIdAndDeletedAtIsNull(createdById); + + return pickCommentTotal + techCommentTotal; + } +} diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/MyWrittenCommentDto.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/MyWrittenCommentDto.java new file mode 100644 index 00000000..e4d6df61 --- /dev/null +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/MyWrittenCommentDto.java @@ -0,0 +1,33 @@ +package com.dreamypatisiel.devdevdev.domain.repository.comment; + +import com.querydsl.core.annotations.QueryProjection; +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public class MyWrittenCommentDto { + private Long postId; + private String postTitle; + private Long commentId; + private String commentType; + private String commentContents; + private Long commentRecommendTotalCount; + private LocalDateTime commentCreatedAt; + private String pickOptionTitle; + private String pickOptionType; + + @QueryProjection + public MyWrittenCommentDto(Long postId, String postTitle, Long commentId, String commentType, + String commentContents, Long commentRecommendTotalCount, LocalDateTime commentCreatedAt, + String pickOptionTitle, String pickOptionType) { + this.postId = postId; + this.postTitle = postTitle; + this.commentId = commentId; + this.commentType = commentType; + this.commentContents = commentContents; + this.commentRecommendTotalCount = commentRecommendTotalCount; + this.commentCreatedAt = commentCreatedAt; + this.pickOptionTitle = pickOptionTitle; + this.pickOptionType = pickOptionType; + } +} diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/mybatis/CommentMapper.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/mybatis/CommentMapper.java new file mode 100644 index 00000000..a8976693 --- /dev/null +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/comment/mybatis/CommentMapper.java @@ -0,0 +1,15 @@ +package com.dreamypatisiel.devdevdev.domain.repository.comment.mybatis; + +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +@Mapper +public interface CommentMapper { + List findByMemberIdAndPickCommentIdAndTechCommentIdOrderByCommentCreatedAtDesc( + @Param("memberId") Long memberId, + @Param("pickCommentId") Long pickCommentId, + @Param("techCommentId") Long techCommentId, + @Param("limit") int limit); +} diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickCommentRepository.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickCommentRepository.java index fb2f287f..85c9ebb9 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickCommentRepository.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickCommentRepository.java @@ -33,4 +33,6 @@ List findWithMemberWithPickWithPickVoteWithPickCommentRecommendsByO Long countByOriginParentIdIn(Set pickIds); Long countByPickIdAndOriginParentIsNullAndParentIsNullAndDeletedAtIsNull(Long pickId); + + Long countByCreatedByIdAndDeletedAtIsNull(Long createdById); } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryCustom.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryCustom.java index 39b5b5ef..0aff36ae 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryCustom.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryCustom.java @@ -2,7 +2,9 @@ import com.dreamypatisiel.devdevdev.domain.entity.PickComment; import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType; +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentSort; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; import java.util.EnumSet; import java.util.List; import org.springframework.data.domain.Pageable; @@ -17,4 +19,7 @@ Slice findOriginParentPickCommentsByCursor(Pageable pageable, Long List findOriginParentPickCommentsByPickIdAndPickOptionTypeIn(Long pickId, EnumSet pickOptionTypes); + + SliceCustom findMyWrittenPickCommentsByCursor(Long memberId, Long pickCommentId, + Pageable pageable); } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryImpl.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryImpl.java index e65a96c1..f67f74f5 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryImpl.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/pick/custom/PickCommentRepositoryImpl.java @@ -9,9 +9,14 @@ import com.dreamypatisiel.devdevdev.domain.entity.PickComment; import com.dreamypatisiel.devdevdev.domain.entity.enums.ContentStatus; import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType; +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; +import com.dreamypatisiel.devdevdev.domain.repository.comment.QMyWrittenCommentDto; import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentSort; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentFilter; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPQLQueryFactory; import java.util.Arrays; import java.util.EnumSet; @@ -83,6 +88,41 @@ public List findOriginParentPickCommentsByPickIdAndPickOptionTypeIn .fetch(); } + @Override + public SliceCustom findMyWrittenPickCommentsByCursor(Long memberId, Long pickCommentId, + Pageable pageable) { + // 회원이 작성한 픽픽픽 댓글 조회 + List contents = query.select( + new QMyWrittenCommentDto(pick.id, + pick.title.title, + pickComment.id, + Expressions.constant(MyWrittenCommentFilter.PICK.name()), + pickComment.contents.commentContents, + pickComment.recommendTotalCount.count, + pickComment.createdAt, + pickOption.title.title, + pickOption.pickOptionType.stringValue())) + .from(pickComment) + .leftJoin(pickComment.pickVote, pickVote) + .leftJoin(pickVote.pickOption, pickOption) + .innerJoin(pick).on(pick.id.eq(pickComment.pick.id).and(pick.contentStatus.eq(ContentStatus.APPROVAL))) + .where(pickComment.createdBy.id.eq(memberId) + .and(pickComment.deletedAt.isNull()) + .and(pickComment.id.lt(pickCommentId))) + .orderBy(pickComment.createdAt.desc()) + .limit(pageable.getPageSize()) + .fetch(); + + // 회원이 작성한 픽픽픽 댓글 총 갯수(삭제 미포함) + long totalElements = query.select(pickComment.count()) + .from(pickComment) + .where(pickComment.createdBy.id.eq(memberId) + .and(pickComment.deletedAt.isNull())) + .fetchCount(); + + return new SliceCustom<>(contents, pageable, hasNextPage(contents, pageable.getPageSize()), totalElements); + } + private static BooleanExpression pickOptionTypeIn(EnumSet pickOptionTypes) { if (ObjectUtils.isEmpty(pickOptionTypes)) { return null; @@ -131,7 +171,7 @@ private OrderSpecifier pickCommentSort(PickCommentSort pickCommentSort) { .orElse(PickCommentSort.LATEST).getOrderSpecifierByPickCommentSort(); } - private boolean hasNextPage(List contents, int pageSize) { + private boolean hasNextPage(List contents, int pageSize) { return contents.size() >= pageSize; } } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/TechCommentRepository.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/TechCommentRepository.java index 35e741b4..ef20d71c 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/TechCommentRepository.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/TechCommentRepository.java @@ -23,4 +23,6 @@ List findWithMemberWithTechArticleByOriginParentIdInAndParentIsNotN Set originParentIds); Long countByTechArticleIdAndOriginParentIsNullAndParentIsNullAndDeletedAtIsNull(Long techArticleId); + + Long countByCreatedByIdAndDeletedAtIsNull(Long createdById); } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryCustom.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryCustom.java index f420e2f9..7ab763c0 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryCustom.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryCustom.java @@ -1,7 +1,9 @@ package com.dreamypatisiel.devdevdev.domain.repository.techArticle.custom; import com.dreamypatisiel.devdevdev.domain.entity.TechComment; +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechCommentSort; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; import java.util.List; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -11,4 +13,7 @@ Slice findOriginParentTechCommentsByCursor(Long techArticleId, Long TechCommentSort techCommentSort, Pageable pageable); List findOriginParentTechBestCommentsByTechArticleIdAndOffset(Long techArticleId, int size); + + SliceCustom findMyWrittenTechCommentsByCursor(Long memberId, Long techCommentId, + Pageable pageable); } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryImpl.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryImpl.java index 71f7a79f..581eed00 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryImpl.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/repository/techArticle/custom/TechCommentRepositoryImpl.java @@ -1,24 +1,28 @@ package com.dreamypatisiel.devdevdev.domain.repository.techArticle.custom; +import static com.dreamypatisiel.devdevdev.domain.entity.QMember.member; +import static com.dreamypatisiel.devdevdev.domain.entity.QTechArticle.techArticle; +import static com.dreamypatisiel.devdevdev.domain.entity.QTechComment.techComment; + import com.dreamypatisiel.devdevdev.domain.entity.TechComment; +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; +import com.dreamypatisiel.devdevdev.domain.repository.comment.QMyWrittenCommentDto; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechCommentSort; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentFilter; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPQLQueryFactory; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.domain.SliceImpl; import org.springframework.util.ObjectUtils; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import static com.dreamypatisiel.devdevdev.domain.entity.QMember.member; -import static com.dreamypatisiel.devdevdev.domain.entity.QTechArticle.techArticle; -import static com.dreamypatisiel.devdevdev.domain.entity.QTechComment.techComment; - @RequiredArgsConstructor public class TechCommentRepositoryImpl implements TechCommentRepositoryCustom { @@ -59,6 +63,40 @@ public List findOriginParentTechBestCommentsByTechArticleIdAndOffse .fetch(); } + @Override + public SliceCustom findMyWrittenTechCommentsByCursor(Long memberId, Long techCommentId, + Pageable pageable) { + + // 회원이 작성한 기술블로그 댓글 조회 + List contents = query.select( + new QMyWrittenCommentDto(techArticle.id, + techArticle.title.title, + techComment.id, + Expressions.constant(MyWrittenCommentFilter.TECH_ARTICLE.name()), + techComment.contents.commentContents, + techComment.recommendTotalCount.count, + techComment.createdAt, + Expressions.nullExpression(), + Expressions.nullExpression())) + .from(techComment) + .innerJoin(techComment.techArticle, techArticle) + .where(techComment.createdBy.id.eq(memberId) + .and(techComment.deletedAt.isNull()) + .and(techComment.id.lt(techCommentId))) + .orderBy(techComment.createdAt.desc()) + .limit(pageable.getPageSize()) + .fetch(); + + // 회원이 작성한 기술 블로그 댓글 총 갯수(삭제 미포함) + long totalElements = query.select(techComment.count()) + .from(techComment) + .where(techComment.createdBy.id.eq(memberId) + .and(techComment.deletedAt.isNull())) + .fetchCount(); + + return new SliceCustom<>(contents, pageable, hasNextPage(contents, pageable.getPageSize()), totalElements); + } + private BooleanExpression getCursorCondition(TechCommentSort techCommentSort, Long techCommentId) { if (ObjectUtils.isEmpty(techCommentId)) { return null; @@ -87,7 +125,7 @@ private OrderSpecifier techCommentSort(TechCommentSort techCommentSort) { .orElse(TechCommentSort.LATEST).getOrderSpecifierByTechCommentSort(); } - private boolean hasNextPage(List contents, int pageSize) { + private boolean hasNextPage(List contents, int pageSize) { return contents.size() >= pageSize; } } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberService.java b/src/main/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberService.java index ae37af75..ae0a1772 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberService.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberService.java @@ -10,6 +10,8 @@ import com.dreamypatisiel.devdevdev.domain.entity.SurveyVersionQuestionMapper; import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CustomSurveyAnswer; +import com.dreamypatisiel.devdevdev.domain.repository.comment.CommentRepository; +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; import com.dreamypatisiel.devdevdev.domain.repository.pick.PickRepository; import com.dreamypatisiel.devdevdev.domain.repository.survey.SurveyAnswerRepository; import com.dreamypatisiel.devdevdev.domain.repository.survey.SurveyQuestionOptionRepository; @@ -17,18 +19,22 @@ import com.dreamypatisiel.devdevdev.domain.repository.survey.custom.SurveyAnswerJdbcTemplateRepository; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.BookmarkSort; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechArticleRepository; -import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.CompanyResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyQuestionResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.pick.MyPickMainResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.TechArticleMainResponse; import com.dreamypatisiel.devdevdev.domain.service.techArticle.techArticle.TechArticleCommonService; import com.dreamypatisiel.devdevdev.elastic.domain.document.ElasticTechArticle; import com.dreamypatisiel.devdevdev.exception.SurveyException; import com.dreamypatisiel.devdevdev.global.common.MemberProvider; import com.dreamypatisiel.devdevdev.global.common.TimeProvider; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentFilter; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentRequest; import com.dreamypatisiel.devdevdev.web.dto.request.member.RecordMemberExitSurveyAnswerRequest; import com.dreamypatisiel.devdevdev.web.dto.request.member.RecordMemberExitSurveyQuestionOptionsRequest; +import com.dreamypatisiel.devdevdev.web.dto.response.comment.MyWrittenCommentResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyQuestionResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.pick.MyPickMainResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.CompanyResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.TechArticleMainResponse; import java.util.List; import java.util.Map; import java.util.Objects; @@ -55,6 +61,7 @@ public class MemberService { private final TimeProvider timeProvider; private final SurveyQuestionOptionRepository surveyQuestionOptionRepository; private final SurveyAnswerJdbcTemplateRepository surveyAnswerJdbcTemplateRepository; + private final CommentRepository commentRepository; /** * 회원 탈퇴 회원의 북마크와 회원 정보를 삭제합니다. @@ -169,11 +176,12 @@ public void recordMemberExitSurveyAnswer(RecordMemberExitSurveyAnswerRequest rec private SurveyAnswer createSurveyAnswerBy(SurveyQuestionOption option, Map surveyQuestionOptions, Member findMember) { + if (!surveyQuestionOptions.containsKey(option.getId())) { return null; } - // surveyQuestionOptions 에 알맞은 키의 값이 존재하면 + // surveyQuestionOptions 에 알맞은 키의 값이 존재하면 String message = surveyQuestionOptions.get(option.getId()).getMessage(); SurveyQuestion surveyQuestion = option.getSurveyQuestion(); @@ -188,7 +196,6 @@ private SurveyAnswer createSurveyAnswerBy(SurveyQuestionOption option, surveyQuestion, option); } - /** * 회원 자신이 북마크한 기술블로그를 조회합니다. */ @@ -226,4 +233,34 @@ private Stream mapToTechArticlesResponse(TechArticle te .map(elasticTechArticle -> TechArticleMainResponse.of(techArticle, elasticTechArticle, CompanyResponse.from(techArticle.getCompany()), member)); } + + /** + * @Note: 회원이 작성한 댓글을 조회합니다.(삭제된 댓글 미포함) + * @Author: 장세웅 + * @Since: 2024.12.31 + */ + public SliceCustom findMyWrittenComments(Pageable pageable, + MyWrittenCommentRequest myWrittenCommentRequest, + Authentication authentication) { + + Long pickCommentId = myWrittenCommentRequest.getPickCommentId(); + Long techCommentId = myWrittenCommentRequest.getTechCommentId(); + MyWrittenCommentFilter myWrittenCommentSort = myWrittenCommentRequest.getCommentFilter(); + + // 회원 조회 + Member findMember = memberProvider.getMemberByAuthentication(authentication); + + // 회원이 작성한 댓글 조회 + SliceCustom findMyWrittenCommentsDto = commentRepository.findMyWrittenCommentsByCursor( + findMember.getId(), pickCommentId, techCommentId, myWrittenCommentSort, pageable); + + // 데이터 가공 + List myWrittenCommentResponses = MyWrittenCommentResponse.from( + findMyWrittenCommentsDto.getContent()); + + boolean hasNext = findMyWrittenCommentsDto.hasNext(); + long totalElements = findMyWrittenCommentsDto.getTotalElements(); + + return new SliceCustom<>(myWrittenCommentResponses, pageable, hasNext, totalElements); + } } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/global/security/jwt/model/TokenExpireTime.java b/src/main/java/com/dreamypatisiel/devdevdev/global/security/jwt/model/TokenExpireTime.java index 210b06ee..c3f5b6ab 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/global/security/jwt/model/TokenExpireTime.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/global/security/jwt/model/TokenExpireTime.java @@ -3,4 +3,5 @@ public class TokenExpireTime { public static final long ACCESS_TOKEN_EXPIRE_TIME = 1_000 * 60 * 30; // 30분 public static final long REFRESH_TOKEN_EXPIRE_TIME = 1_000 * 60 * 60 * 24 * 7; // 7일 + public static final long TEST_TOKEN_EXPIRE_TIME = 1_000 * 60 * 60 * 24 * 21; // 21일 } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/web/controller/member/MypageController.java b/src/main/java/com/dreamypatisiel/devdevdev/web/controller/member/MypageController.java index 9b73db4c..655def08 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/web/controller/member/MypageController.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/web/controller/member/MypageController.java @@ -2,18 +2,21 @@ import com.dreamypatisiel.devdevdev.domain.repository.techArticle.BookmarkSort; import com.dreamypatisiel.devdevdev.domain.service.member.MemberService; -import com.dreamypatisiel.devdevdev.domain.service.techArticle.TechArticleServiceStrategy; import com.dreamypatisiel.devdevdev.global.security.jwt.model.JwtCookieConstant; import com.dreamypatisiel.devdevdev.global.utils.AuthenticationMemberUtils; import com.dreamypatisiel.devdevdev.global.utils.CookieUtils; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentRequest; import com.dreamypatisiel.devdevdev.web.dto.request.member.RecordMemberExitSurveyAnswerRequest; import com.dreamypatisiel.devdevdev.web.dto.response.BasicResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.comment.MyWrittenCommentResponse; import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyResponse; import com.dreamypatisiel.devdevdev.web.dto.response.pick.MyPickMainResponse; import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.TechArticleMainResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -24,6 +27,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -36,7 +40,6 @@ @RequiredArgsConstructor public class MypageController { - private final TechArticleServiceStrategy techArticleServiceStrategy; private final MemberService memberService; @Operation(summary = "북마크 목록 조회") @@ -101,4 +104,18 @@ public ResponseEntity> recordMemberExitSurvey(@RequestBody @ return ResponseEntity.ok(BasicResponse.success()); } + + @Operation(summary = "내가 작성한 댓글 조회", description = "본인이 작성한 댓글을 무한 스크롤 방식으로 조회합니다.") + @GetMapping("/mypage/comments") + public ResponseEntity>> getMyWrittenComments( + @PageableDefault(size = 6) Pageable pageable, + @Valid @ModelAttribute MyWrittenCommentRequest myWrittenCommentRequest) { + + Authentication authentication = AuthenticationMemberUtils.getAuthentication(); + + SliceCustom myWrittenComments = memberService.findMyWrittenComments(pageable, + myWrittenCommentRequest, authentication); + + return ResponseEntity.ok(BasicResponse.success(myWrittenComments)); + } } diff --git a/src/main/java/com/dreamypatisiel/devdevdev/web/dto/request/comment/MyWrittenCommentFilter.java b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/request/comment/MyWrittenCommentFilter.java new file mode 100644 index 00000000..b99149c7 --- /dev/null +++ b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/request/comment/MyWrittenCommentFilter.java @@ -0,0 +1,7 @@ +package com.dreamypatisiel.devdevdev.web.dto.request.comment; + +public enum MyWrittenCommentFilter { + ALL, + PICK, + TECH_ARTICLE +} diff --git a/src/main/java/com/dreamypatisiel/devdevdev/web/dto/request/comment/MyWrittenCommentRequest.java b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/request/comment/MyWrittenCommentRequest.java new file mode 100644 index 00000000..16127f30 --- /dev/null +++ b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/request/comment/MyWrittenCommentRequest.java @@ -0,0 +1,18 @@ +package com.dreamypatisiel.devdevdev.web.dto.request.comment; + +import java.util.Objects; +import lombok.Data; + +@Data +public class MyWrittenCommentRequest { + private Long pickCommentId; + private Long techCommentId; + private MyWrittenCommentFilter commentFilter; + + public MyWrittenCommentRequest(Long pickCommentId, Long techCommentId, + MyWrittenCommentFilter myWrittenCommentSort) { + this.pickCommentId = Objects.requireNonNullElse(pickCommentId, Long.MAX_VALUE); + this.techCommentId = Objects.requireNonNullElse(techCommentId, Long.MAX_VALUE); + this.commentFilter = Objects.requireNonNullElse(myWrittenCommentSort, MyWrittenCommentFilter.ALL); + } +} diff --git a/src/main/java/com/dreamypatisiel/devdevdev/web/dto/response/comment/MyWrittenCommentResponse.java b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/response/comment/MyWrittenCommentResponse.java new file mode 100644 index 00000000..83204bbc --- /dev/null +++ b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/response/comment/MyWrittenCommentResponse.java @@ -0,0 +1,73 @@ +package com.dreamypatisiel.devdevdev.web.dto.response.comment; + +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; +import com.dreamypatisiel.devdevdev.global.common.TimeProvider; +import com.dreamypatisiel.devdevdev.web.dto.util.CommentResponseUtil; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonFormat.Shape; +import java.time.LocalDateTime; +import java.util.List; +import javax.annotation.Nullable; +import lombok.Builder; +import lombok.Data; + +@Data +public class MyWrittenCommentResponse { + private String uniqueCommentId; + private Long postId; + private String postTitle; + private Long commentId; + private String commentType; + private String commentContents; + private Long commentRecommendTotalCount; + + @JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = TimeProvider.DEFAULT_ZONE_ID) + private LocalDateTime commentCreatedAt; + + private String pickOptionTitle; + private String pickOptionType; + + @Builder + public MyWrittenCommentResponse(String uniqueCommentId, Long postId, String postTitle, + Long commentId, String commentType, + String commentContents, Long commentRecommendTotalCount, + LocalDateTime commentCreatedAt, @Nullable String pickOptionTitle, + @Nullable String pickOptionType) { + this.uniqueCommentId = uniqueCommentId; + this.postId = postId; + this.postTitle = postTitle; + this.commentId = commentId; + this.commentType = commentType; + this.commentContents = commentContents; + this.commentRecommendTotalCount = commentRecommendTotalCount; + this.commentCreatedAt = commentCreatedAt; + this.pickOptionTitle = pickOptionTitle; + this.pickOptionType = pickOptionType; + } + + public static MyWrittenCommentResponse from(MyWrittenCommentDto myWrittenCommentDto) { + + Long postId = myWrittenCommentDto.getPostId(); + Long commentId = myWrittenCommentDto.getCommentId(); + String commentType = myWrittenCommentDto.getCommentType(); + + return MyWrittenCommentResponse.builder() + .uniqueCommentId(CommentResponseUtil.createUniqueCommentId(commentType, postId, commentId)) + .postId(postId) + .postTitle(myWrittenCommentDto.getPostTitle()) + .commentId(commentId) + .commentType(commentType) + .commentContents(myWrittenCommentDto.getCommentContents()) + .commentRecommendTotalCount(myWrittenCommentDto.getCommentRecommendTotalCount()) + .commentCreatedAt(myWrittenCommentDto.getCommentCreatedAt()) + .pickOptionTitle(myWrittenCommentDto.getPickOptionTitle()) + .pickOptionType(myWrittenCommentDto.getPickOptionType()) + .build(); + } + + public static List from(List myWrittenCommentsDto) { + return myWrittenCommentsDto.stream() + .map(MyWrittenCommentResponse::from) + .toList(); + } +} diff --git a/src/main/java/com/dreamypatisiel/devdevdev/web/dto/response/member/MemberExitSurveyAnswerResponse.java b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/response/member/MemberExitSurveyAnswerResponse.java deleted file mode 100644 index f6f50ecf..00000000 --- a/src/main/java/com/dreamypatisiel/devdevdev/web/dto/response/member/MemberExitSurveyAnswerResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dreamypatisiel.devdevdev.web.dto.response.member; - -import java.util.List; -import lombok.Data; - -@Data -public class MemberExitSurveyAnswerResponse { - private final List id; - - public MemberExitSurveyAnswerResponse(List id) { - this.id = id; - } -} diff --git a/src/main/java/com/dreamypatisiel/devdevdev/web/dto/util/CommentResponseUtil.java b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/util/CommentResponseUtil.java index 001d2ad6..e8c66ec1 100644 --- a/src/main/java/com/dreamypatisiel/devdevdev/web/dto/util/CommentResponseUtil.java +++ b/src/main/java/com/dreamypatisiel/devdevdev/web/dto/util/CommentResponseUtil.java @@ -10,6 +10,7 @@ import javax.annotation.Nullable; public class CommentResponseUtil { + public static String getCommentByPickCommentStatus(PickComment pickComment) { if (pickComment.isDeleted()) { // 댓글 작성자에 의해 삭제된 경우 @@ -87,4 +88,8 @@ public static boolean isTechCommentRecommendedByMember(@Nullable Member member, return recommends.map(TechCommentRecommend::isRecommended).orElse(false); } + + public static String createUniqueCommentId(String commentType, Long postId, Long commentId) { + return commentType + "_" + postId + "_" + commentId; + } } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 61b6f2ef..1f004d1b 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -61,6 +61,14 @@ spring: max-idle: 8 min-idle: 2 +#MyBatis +mybatis: + type-aliases-package: com.dreamypatisiel.devdevdev.domain.repository + configuration: + map-underscore-to-camel-case: true + mapper-locations: classpath:mapper/**/*.xml + logging: level: - org.hibernate.SQL: DEBUG \ No newline at end of file + org.hibernate.SQL: DEBUG + com.dreamypatisiel.devdevdev: TRACE diff --git a/src/main/resources/mapper/commment/Comment.xml b/src/main/resources/mapper/commment/Comment.xml new file mode 100644 index 00000000..cb5f4e93 --- /dev/null +++ b/src/main/resources/mapper/commment/Comment.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/comment/CommentRepositoryTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/comment/CommentRepositoryTest.java new file mode 100644 index 00000000..73769021 --- /dev/null +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/comment/CommentRepositoryTest.java @@ -0,0 +1,260 @@ +package com.dreamypatisiel.devdevdev.domain.repository.comment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +import com.dreamypatisiel.devdevdev.domain.entity.Company; +import com.dreamypatisiel.devdevdev.domain.entity.Member; +import com.dreamypatisiel.devdevdev.domain.entity.Pick; +import com.dreamypatisiel.devdevdev.domain.entity.PickComment; +import com.dreamypatisiel.devdevdev.domain.entity.PickOption; +import com.dreamypatisiel.devdevdev.domain.entity.PickVote; +import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; +import com.dreamypatisiel.devdevdev.domain.entity.TechComment; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.CommentContents; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; +import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType; +import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; +import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; +import com.dreamypatisiel.devdevdev.domain.repository.CompanyRepository; +import com.dreamypatisiel.devdevdev.domain.repository.comment.mybatis.CommentMapper; +import com.dreamypatisiel.devdevdev.domain.repository.member.MemberRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickOptionRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickVoteRepository; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechArticleRepository; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechCommentRepository; +import com.dreamypatisiel.devdevdev.global.security.oauth2.model.SocialMemberDto; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentFilter; +import jakarta.transaction.Transactional; +import java.time.LocalDateTime; +import java.util.Optional; +import org.assertj.core.groups.Tuple; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.data.auditing.AuditingHandler; +import org.springframework.data.auditing.DateTimeProvider; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +@SpringBootTest +@Transactional +class CommentRepositoryTest { + + @Autowired + CommentRepository commentRepository; + @Autowired + CommentMapper commentMapper; + @Autowired + MemberRepository memberRepository; + @Autowired + PickRepository pickRepository; + @Autowired + PickCommentRepository pickCommentRepository; + @Autowired + PickVoteRepository pickVoteRepository; + @Autowired + PickOptionRepository pickOptionRepository; + @Autowired + CompanyRepository companyRepository; + @Autowired + TechArticleRepository techArticleRepository; + @Autowired + TechCommentRepository techCommentRepository; + + @MockBean + DateTimeProvider dateTimeProvider; + + @SpyBean + AuditingHandler auditingHandler; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + auditingHandler.setDateTimeProvider(dateTimeProvider); + } + + @Test + @DisplayName("회원이 작성하고 삭제상태가 아닌 픽픽픽, 기술블로그 댓글을 작성시간 내림차순으로 조회한다.") + void findMyWrittenCommentsByCursorCursor() { + // given + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0))); + + // 회원 생성 + SocialMemberDto socialMemberDto = createSocialDto("user", "name", "nickname", "password", "user@gmail.com", + SocialType.KAKAO.name(), Role.ROLE_USER.name()); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + // 픽픽픽 생성 + Pick pick = createPick("픽픽픽", member); + pickRepository.save(pick); + + // 픽픽픽 옵션 생성 + PickOption pickOption = createPickOption(pick, "픽픽픽 A", PickOptionType.firstPickOption); + pickOptionRepository.save(pickOption); + + // 픽픽픽 투표 생성 + PickVote pickVote = createPickVote(pick, pickOption, member); + pickVoteRepository.save(pickVote); + + // 픽픽픽 댓글 생성 + PickComment pickComment1 = createPickComment(pick, member, pickVote, null, null, "픽픽픽 댓글1", true); + PickComment pickComment2 = createPickComment(pick, member, null, pickComment1, pickComment1, "픽픽픽 댓글2", false); + PickComment pickComment3 = createPickComment(pick, member, null, pickComment1, pickComment2, "픽픽픽 댓글3", false); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0))); + pickCommentRepository.save(pickComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 2, 1, 0, 0))); + pickCommentRepository.save(pickComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 3, 1, 0, 0))); + pickCommentRepository.save(pickComment3); + + // 기술블로그 회사 생성 + Company company = createCompany("DreamyPatisiel"); + companyRepository.save(company); + + // 기술블로그 생성 + TechArticle techArticle = createTechArticle(company, "기술블로그 제목"); + techArticleRepository.save(techArticle); + + // 기술블로그 댓글 생성 + TechComment techComment1 = createTechComment(techArticle, member, null, null, "기술블로그 댓글1"); + TechComment techComment2 = createTechComment(techArticle, member, techComment1, techComment1, "기술블로그 댓글2"); + TechComment techComment3 = createTechComment(techArticle, member, techComment1, techComment2, "기술블로그 댓글3"); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 4, 1, 0, 0))); + techCommentRepository.save(techComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 5, 1, 0, 0))); + techCommentRepository.save(techComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 6, 1, 0, 0))); + techCommentRepository.save(techComment3); + + // when + Long techCommentId = techComment3.getId() + 1L; + Long pickCommentId = pickComment3.getId() + 1L; + Pageable pageable = PageRequest.of(0, 6); + + // when + SliceCustom findMyWrittenComments = commentRepository.findMyWrittenCommentsByCursor( + member.getId(), pickCommentId, techCommentId, MyWrittenCommentFilter.ALL, pageable); + + // then + assertThat(findMyWrittenComments.getTotalElements()).isEqualTo(6); + assertThat(findMyWrittenComments.getContent()).hasSize(6) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "pickOptionTitle", "pickOptionType", "commentCreatedAt") + .containsExactly( + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment3.getId(), + "TECH_ARTICLE", techComment3.getContents().getCommentContents(), + null, null, + techComment3.getCreatedAt()), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment2.getId(), + "TECH_ARTICLE", techComment2.getContents().getCommentContents(), + null, null, + techComment2.getCreatedAt()), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment1.getId(), + "TECH_ARTICLE", techComment1.getContents().getCommentContents(), + null, null, + techComment1.getCreatedAt()), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment3.getId(), + "PICK", pickComment3.getContents().getCommentContents(), + null, null, + pickComment3.getCreatedAt()), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment2.getId(), + "PICK", pickComment2.getContents().getCommentContents(), + null, null, + pickComment2.getCreatedAt()), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment1.getId(), + "PICK", pickComment1.getContents().getCommentContents(), + pickOption.getTitle().getTitle(), pickOption.getPickOptionType().name(), + pickComment1.getCreatedAt()) + ); + } + + private static TechComment createTechComment(TechArticle techArticle, Member member, TechComment originParent, + TechComment parent, String contents) { + return TechComment.builder() + .techArticle(techArticle) + .createdBy(member) + .originParent(originParent) + .parent(parent) + .contents(new CommentContents(contents)) + .build(); + } + + private static TechArticle createTechArticle(Company company, String title) { + return TechArticle.builder() + .company(company) + .title(new Title(title)) + .build(); + } + + private static Company createCompany(String companyName) { + return Company.builder() + .name(new CompanyName(companyName)) + .build(); + } + + private static PickOption createPickOption(Pick pick, String title, PickOptionType pickOptionType) { + return PickOption.builder() + .pick(pick) + .title(new Title(title)) + .pickOptionType(pickOptionType) + .build(); + } + + private static PickVote createPickVote(Pick pick, PickOption pickOption, Member member) { + return PickVote.builder() + .pick(pick) + .pickOption(pickOption) + .member(member) + .build(); + } + + private static PickComment createPickComment(Pick pick, Member member, PickVote pickVote, PickComment originParent, + PickComment parent, String contents, Boolean isPublic) { + return PickComment.builder() + .pick(pick) + .createdBy(member) + .pickVote(pickVote) + .originParent(originParent) + .parent(parent) + .contents(new CommentContents(contents)) + .isPublic(isPublic) + .build(); + } + + private static Pick createPick(String title, Member member) { + return Pick.builder() + .title(new Title(title)) + .member(member) + .build(); + } + + private SocialMemberDto createSocialDto(String userId, String name, String nickName, String password, String email, + String socialType, String role) { + return SocialMemberDto.builder() + .userId(userId) + .name(name) + .nickname(nickName) + .password(password) + .email(email) + .socialType(SocialType.valueOf(socialType)) + .role(Role.valueOf(role)) + .build(); + } +} \ No newline at end of file diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/comment/mybatis/CommentMapperTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/comment/mybatis/CommentMapperTest.java new file mode 100644 index 00000000..4fcdf8ea --- /dev/null +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/comment/mybatis/CommentMapperTest.java @@ -0,0 +1,254 @@ +package com.dreamypatisiel.devdevdev.domain.repository.comment.mybatis; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +import com.dreamypatisiel.devdevdev.domain.entity.Company; +import com.dreamypatisiel.devdevdev.domain.entity.Member; +import com.dreamypatisiel.devdevdev.domain.entity.Pick; +import com.dreamypatisiel.devdevdev.domain.entity.PickComment; +import com.dreamypatisiel.devdevdev.domain.entity.PickOption; +import com.dreamypatisiel.devdevdev.domain.entity.PickVote; +import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; +import com.dreamypatisiel.devdevdev.domain.entity.TechComment; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.CommentContents; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; +import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType; +import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; +import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; +import com.dreamypatisiel.devdevdev.domain.repository.CompanyRepository; +import com.dreamypatisiel.devdevdev.domain.repository.comment.MyWrittenCommentDto; +import com.dreamypatisiel.devdevdev.domain.repository.member.MemberRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickOptionRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickVoteRepository; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechArticleRepository; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechCommentRepository; +import com.dreamypatisiel.devdevdev.global.security.oauth2.model.SocialMemberDto; +import jakarta.transaction.Transactional; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import org.assertj.core.groups.Tuple; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.data.auditing.AuditingHandler; +import org.springframework.data.auditing.DateTimeProvider; + +@SpringBootTest +@Transactional +class CommentMapperTest { + + @Autowired + CommentMapper commentMapper; + @Autowired + MemberRepository memberRepository; + @Autowired + PickRepository pickRepository; + @Autowired + PickCommentRepository pickCommentRepository; + @Autowired + PickVoteRepository pickVoteRepository; + @Autowired + PickOptionRepository pickOptionRepository; + @Autowired + CompanyRepository companyRepository; + @Autowired + TechArticleRepository techArticleRepository; + @Autowired + TechCommentRepository techCommentRepository; + + @MockBean + DateTimeProvider dateTimeProvider; + + @SpyBean + AuditingHandler auditingHandler; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + auditingHandler.setDateTimeProvider(dateTimeProvider); + } + + @Test + @DisplayName("회원이 작성한 픽픽픽, 기술블로그 댓글을 커서 방식으로 작성일시 내림차순으로 조회한다.") + void findByMemberIdAndPickCommentIdAndTechCommentIdOrderByCommentCreatedAtDesc() { + // given + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0))); + + // 회원 생성 + SocialMemberDto socialMemberDto = createSocialDto("user", "name", "nickname", "password", "user@gmail.com", + SocialType.KAKAO.name(), Role.ROLE_USER.name()); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + // 픽픽픽 생성 + Pick pick = createPick("픽픽픽", member); + pickRepository.save(pick); + + // 픽픽픽 옵션 생성 + PickOption pickOption = createPickOption(pick, "픽픽픽 A", PickOptionType.firstPickOption); + pickOptionRepository.save(pickOption); + + // 픽픽픽 투표 생성 + PickVote pickVote = createPickVote(pick, pickOption, member); + pickVoteRepository.save(pickVote); + + // 픽픽픽 댓글 생성 + PickComment pickComment1 = createPickComment(pick, member, pickVote, null, null, "픽픽픽 댓글1", true); + PickComment pickComment2 = createPickComment(pick, member, null, pickComment1, pickComment1, "픽픽픽 댓글2", false); + PickComment pickComment3 = createPickComment(pick, member, null, pickComment1, pickComment2, "픽픽픽 댓글3", false); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0))); + pickCommentRepository.save(pickComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 2, 1, 0, 0))); + pickCommentRepository.save(pickComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 3, 1, 0, 0))); + pickCommentRepository.save(pickComment3); + + // 기술블로그 회사 생성 + Company company = createCompany("DreamyPatisiel"); + companyRepository.save(company); + + // 기술블로그 생성 + TechArticle techArticle = createTechArticle(company, "기술블로그 제목"); + techArticleRepository.save(techArticle); + + // 기술블로그 댓글 생성 + TechComment techComment1 = createTechComment(techArticle, member, null, null, "기술블로그 댓글1"); + TechComment techComment2 = createTechComment(techArticle, member, techComment1, techComment1, "기술블로그 댓글2"); + TechComment techComment3 = createTechComment(techArticle, member, techComment1, techComment2, "기술블로그 댓글3"); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 4, 1, 0, 0))); + techCommentRepository.save(techComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 5, 1, 0, 0))); + techCommentRepository.save(techComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 6, 1, 0, 0))); + techCommentRepository.save(techComment3); + + // when + Long techCommentId = techComment3.getId() + 1L; + Long pickCommentId = pickComment3.getId() + 1L; + + int limit = 6; + + List myWrittenComments = commentMapper.findByMemberIdAndPickCommentIdAndTechCommentIdOrderByCommentCreatedAtDesc( + member.getId(), pickCommentId, techCommentId, limit); + + // then + assertThat(myWrittenComments).hasSize(6) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "pickOptionTitle", "pickOptionType", "commentCreatedAt") + .containsExactly( + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment3.getId(), + "TECH_ARTICLE", techComment3.getContents().getCommentContents(), + null, null, + techComment3.getCreatedAt()), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment2.getId(), + "TECH_ARTICLE", techComment2.getContents().getCommentContents(), + null, null, + techComment2.getCreatedAt()), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment1.getId(), + "TECH_ARTICLE", techComment1.getContents().getCommentContents(), + null, null, + techComment1.getCreatedAt()), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment3.getId(), + "PICK", pickComment3.getContents().getCommentContents(), + null, null, + pickComment3.getCreatedAt()), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment2.getId(), + "PICK", pickComment2.getContents().getCommentContents(), + null, null, + pickComment2.getCreatedAt()), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment1.getId(), + "PICK", pickComment1.getContents().getCommentContents(), + pickOption.getTitle().getTitle(), pickOption.getPickOptionType().name(), + pickComment1.getCreatedAt()) + ); + } + + private static TechComment createTechComment(TechArticle techArticle, Member member, TechComment originParent, + TechComment parent, String contents) { + return TechComment.builder() + .techArticle(techArticle) + .createdBy(member) + .originParent(originParent) + .parent(parent) + .contents(new CommentContents(contents)) + .build(); + } + + private static TechArticle createTechArticle(Company company, String title) { + return TechArticle.builder() + .company(company) + .title(new Title(title)) + .build(); + } + + private static Company createCompany(String companyName) { + return Company.builder() + .name(new CompanyName(companyName)) + .build(); + } + + private static PickOption createPickOption(Pick pick, String title, PickOptionType pickOptionType) { + return PickOption.builder() + .pick(pick) + .title(new Title(title)) + .pickOptionType(pickOptionType) + .build(); + } + + private static PickVote createPickVote(Pick pick, PickOption pickOption, Member member) { + return PickVote.builder() + .pick(pick) + .pickOption(pickOption) + .member(member) + .build(); + } + + private static PickComment createPickComment(Pick pick, Member member, PickVote pickVote, PickComment originParent, + PickComment parent, String contents, Boolean isPublic) { + return PickComment.builder() + .pick(pick) + .createdBy(member) + .pickVote(pickVote) + .originParent(originParent) + .parent(parent) + .contents(new CommentContents(contents)) + .isPublic(isPublic) + .build(); + } + + private static Pick createPick(String title, Member member) { + return Pick.builder() + .title(new Title(title)) + .member(member) + .build(); + } + + private SocialMemberDto createSocialDto(String userId, String name, String nickName, String password, String email, + String socialType, String role) { + return SocialMemberDto.builder() + .userId(userId) + .name(name) + .nickname(nickName) + .password(password) + .email(email) + .socialType(SocialType.valueOf(socialType)) + .role(Role.valueOf(role)) + .build(); + } +} \ No newline at end of file diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickRepositoryTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickRepositoryTest.java index dd937d77..295a43fd 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickRepositoryTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/repository/pick/PickRepositoryTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +import com.dreamypatisiel.devdevdev.domain.entity.Member; import com.dreamypatisiel.devdevdev.domain.entity.Pick; import com.dreamypatisiel.devdevdev.domain.entity.PickOption; import com.dreamypatisiel.devdevdev.domain.entity.PickOptionImage; @@ -49,6 +50,9 @@ class PickRepositoryTest { @DisplayName("findPicksByCursor 쿼리 확인") void findPicksByCursor() { // given + Member member = createMember("사용자"); + memberRepository.save(member); + PickOption pickOption1 = createPickOption(new Title("픽옵션1"), new PickOptionContents("픽콘텐츠1"), new Count(1), PickOptionType.firstPickOption); PickOption pickOption2 = createPickOption(new Title("픽옵션2"), new PickOptionContents("픽콘텐츠2"), new Count(2), @@ -66,19 +70,26 @@ void findPicksByCursor() { Count pick2ViewTotalCount = new Count(1); Count pick1CommentTotalCount = new Count(0); Count pick2CommentTotalCount = new Count(0); - Pick pick1 = createPick(new Title("픽1타이틀"), pick1VoteTotalCount, pick1ViewTotalCount, pick1CommentTotalCount, + Pick pick1 = createPick(member, new Title("픽1타이틀"), pick1VoteTotalCount, pick1ViewTotalCount, + pick1CommentTotalCount, thumbnailUrl, author, List.of(pickOption1, pickOption2), List.of()); - Pick pick2 = createPick(new Title("픽2타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, pick2CommentTotalCount, + Pick pick2 = createPick(member, new Title("픽2타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, + pick2CommentTotalCount, thumbnailUrl, author, List.of(pickOption3, pickOption4), List.of()); - Pick pick3 = createPick(new Title("픽3타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, pick2CommentTotalCount, + Pick pick3 = createPick(member, new Title("픽3타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, + pick2CommentTotalCount, thumbnailUrl, author, List.of(pickOption3, pickOption4), List.of()); - Pick pick4 = createPick(new Title("픽4타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, pick2CommentTotalCount, + Pick pick4 = createPick(member, new Title("픽4타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, + pick2CommentTotalCount, thumbnailUrl, author, List.of(pickOption3, pickOption4), List.of()); - Pick pick5 = createPick(new Title("픽5타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, pick2CommentTotalCount, + Pick pick5 = createPick(member, new Title("픽5타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, + pick2CommentTotalCount, thumbnailUrl, author, List.of(pickOption3, pickOption4), List.of()); - Pick pick6 = createPick(new Title("픽6타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, pick2CommentTotalCount, + Pick pick6 = createPick(member, new Title("픽6타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, + pick2CommentTotalCount, thumbnailUrl, author, List.of(pickOption3, pickOption4), List.of()); - Pick pick7 = createPick(new Title("픽7타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, pick2CommentTotalCount, + Pick pick7 = createPick(member, new Title("픽7타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, + pick2CommentTotalCount, thumbnailUrl, author, List.of(pickOption3, pickOption4), List.of()); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5, pick6, pick7)); pickOptionRepository.saveAll(List.of(pickOption1, pickOption2, pickOption3, pickOption4)); @@ -96,12 +107,15 @@ void findPicksByCursor() { @DisplayName("조회수 내림차순으로 Pick을 조회한다.") void findPicksByCursorOrderByViewCountDesc() { // given - Pick pick1 = createPickViewTotalCount(new Title("픽1타이틀"), new Count(1)); - Pick pick2 = createPickViewTotalCount(new Title("픽2타이틀"), new Count(2)); - Pick pick3 = createPickViewTotalCount(new Title("픽3타이틀"), new Count(3)); - Pick pick4 = createPickViewTotalCount(new Title("픽4타이틀"), new Count(3)); - Pick pick5 = createPickViewTotalCount(new Title("픽5타이틀"), new Count(4)); - Pick pick6 = createPickViewTotalCount(new Title("픽6타이틀"), new Count(5)); + Member member = createMember("사용자"); + memberRepository.save(member); + + Pick pick1 = createPickViewTotalCount(member, new Title("픽1타이틀"), new Count(1)); + Pick pick2 = createPickViewTotalCount(member, new Title("픽2타이틀"), new Count(2)); + Pick pick3 = createPickViewTotalCount(member, new Title("픽3타이틀"), new Count(3)); + Pick pick4 = createPickViewTotalCount(member, new Title("픽4타이틀"), new Count(3)); + Pick pick5 = createPickViewTotalCount(member, new Title("픽5타이틀"), new Count(4)); + Pick pick6 = createPickViewTotalCount(member, new Title("픽6타이틀"), new Count(5)); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5, pick6)); @@ -122,12 +136,15 @@ void findPicksByCursorOrderByViewCountDesc() { @DisplayName("생성시간 내림차순으로 Pick을 조회한다.") void findPicksByCursorOrderByCreatedAtDesc() { // given - Pick pick1 = createPick(new Title("픽1타이틀")); - Pick pick2 = createPick(new Title("픽2타이틀")); - Pick pick3 = createPick(new Title("픽3타이틀")); - Pick pick4 = createPick(new Title("픽4타이틀")); - Pick pick5 = createPick(new Title("픽5타이틀")); - Pick pick6 = createPick(new Title("픽6타이틀")); + Member member = createMember("사용자"); + memberRepository.save(member); + + Pick pick1 = createPick(member, new Title("픽1타이틀")); + Pick pick2 = createPick(member, new Title("픽2타이틀")); + Pick pick3 = createPick(member, new Title("픽3타이틀")); + Pick pick4 = createPick(member, new Title("픽4타이틀")); + Pick pick5 = createPick(member, new Title("픽5타이틀")); + Pick pick6 = createPick(member, new Title("픽6타이틀")); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5, pick6)); @@ -148,12 +165,15 @@ void findPicksByCursorOrderByCreatedAtDesc() { @DisplayName("댓글수 내림차순으로 Pick을 조회한다.") void findPicksByCursorOrderByDesc() { // given - Pick pick1 = createPickCommentTotalCount(new Title("픽1타이틀"), new Count(1)); - Pick pick2 = createPickCommentTotalCount(new Title("픽2타이틀"), new Count(2)); - Pick pick3 = createPickCommentTotalCount(new Title("픽3타이틀"), new Count(3)); - Pick pick4 = createPickCommentTotalCount(new Title("픽4타이틀"), new Count(3)); - Pick pick5 = createPickCommentTotalCount(new Title("픽5타이틀"), new Count(4)); - Pick pick6 = createPickCommentTotalCount(new Title("픽6타이틀"), new Count(5)); + Member member = createMember("사용자"); + memberRepository.save(member); + + Pick pick1 = createPickCommentTotalCount(member, new Title("픽1타이틀"), new Count(1)); + Pick pick2 = createPickCommentTotalCount(member, new Title("픽2타이틀"), new Count(2)); + Pick pick3 = createPickCommentTotalCount(member, new Title("픽3타이틀"), new Count(3)); + Pick pick4 = createPickCommentTotalCount(member, new Title("픽4타이틀"), new Count(3)); + Pick pick5 = createPickCommentTotalCount(member, new Title("픽5타이틀"), new Count(4)); + Pick pick6 = createPickCommentTotalCount(member, new Title("픽6타이틀"), new Count(5)); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5, pick6)); @@ -170,18 +190,28 @@ void findPicksByCursorOrderByDesc() { ); } + private static Member createMember(String name) { + return Member.builder() + .name(name) + .isDeleted(false) + .build(); + } + @Test @DisplayName("인기순으로 Pick을 조회한다." + "(현재 가중치 = 댓글수:" + PickPopularScorePolicy.COMMENT_WEIGHT + ", 투표수:" + PickPopularScorePolicy.VOTE_WEIGHT + ", 조회수:" + PickPopularScorePolicy.VIEW_WEIGHT + ")") void findPicksByCursorOrderByPopular() { // given - Pick pick1 = createPickByPopularScore(new Title("픽1타이틀"), new Count(1)); - Pick pick2 = createPickByPopularScore(new Title("픽2타이틀"), new Count(2)); - Pick pick3 = createPickByPopularScore(new Title("픽3타이틀"), new Count(3)); - Pick pick4 = createPickByPopularScore(new Title("픽4타이틀"), new Count(3)); - Pick pick5 = createPickByPopularScore(new Title("픽5타이틀"), new Count(4)); - Pick pick6 = createPickByPopularScore(new Title("픽6타이틀"), new Count(5)); + Member member = createMember("사용자"); + memberRepository.save(member); + + Pick pick1 = createPickByPopularScore(member, new Title("픽1타이틀"), new Count(1)); + Pick pick2 = createPickByPopularScore(member, new Title("픽2타이틀"), new Count(2)); + Pick pick3 = createPickByPopularScore(member, new Title("픽3타이틀"), new Count(3)); + Pick pick4 = createPickByPopularScore(member, new Title("픽4타이틀"), new Count(3)); + Pick pick5 = createPickByPopularScore(member, new Title("픽5타이틀"), new Count(4)); + Pick pick6 = createPickByPopularScore(member, new Title("픽6타이틀"), new Count(5)); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5, pick6)); @@ -203,7 +233,10 @@ void findPicksByCursorOrderByPopular() { @DisplayName("findPickWithPickOptionWithPickVoteWithMemberByPickId 쿼리 확인") void findPickAndPickOptionAndPickOptionImageById() { // given - Pick pick = createPick(new Title("픽1타이틀")); + Member member = createMember("사용자"); + memberRepository.save(member); + + Pick pick = createPick(member, new Title("픽1타이틀")); pickRepository.save(pick); PickOption pickOption1 = createPickOption(new Title("픽옵션1"), new PickOptionContents("픽옵션콘텐츠1"), new Count(1), @@ -260,31 +293,35 @@ private PickOptionImage cratePickOptionImage(String name, PickOption pickOption) return pickOptionImage; } - private Pick createPick(Title title) { + private Pick createPick(Member member, Title title) { return Pick.builder() + .member(member) .title(title) .contentStatus(ContentStatus.APPROVAL) .build(); } - private Pick createPickByPopularScore(Title title, Count popularScore) { + private Pick createPickByPopularScore(Member member, Title title, Count popularScore) { return Pick.builder() + .member(member) .title(title) .popularScore(popularScore) .contentStatus(ContentStatus.APPROVAL) .build(); } - private Pick createPickViewTotalCount(Title title, Count viewTotalCount) { + private Pick createPickViewTotalCount(Member member, Title title, Count viewTotalCount) { return Pick.builder() + .member(member) .title(title) .viewTotalCount(viewTotalCount) .contentStatus(ContentStatus.APPROVAL) .build(); } - private Pick createPickCommentTotalCount(Title title, Count commentTotalCount) { + private Pick createPickCommentTotalCount(Member member, Title title, Count commentTotalCount) { return Pick.builder() + .member(member) .title(title) .commentTotalCount(commentTotalCount) .contentStatus(ContentStatus.APPROVAL) @@ -298,12 +335,13 @@ private Pick createPickVoteTotalCount(Title title, Count voteTotalCount) { .build(); } - private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTotalCount, + private Pick createPick(Member member, Title title, Count pickVoteTotalCount, Count pickViewTotalCount, Count pickcommentTotalCount, String thumbnailUrl, String author, List pickOptions, List pickVotes ) { Pick pick = Pick.builder() + .member(member) .title(title) .voteTotalCount(pickVoteTotalCount) .viewTotalCount(pickViewTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/blame/MemberPickBlameServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/blame/MemberPickBlameServiceTest.java index 7b377c05..20c4dee6 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/blame/MemberPickBlameServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/blame/MemberPickBlameServiceTest.java @@ -82,7 +82,7 @@ void blamePick() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 신고 종류 생성 @@ -124,7 +124,7 @@ void blamePickEtc() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 신고 종류 생성 @@ -185,7 +185,7 @@ void blamePickIsNotApproval(ContentStatus contentStatus) { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", contentStatus, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", contentStatus, new Count(0L)); pickRepository.save(pick); BlamePickDto blamePickDto = new BlamePickDto(pick.getId(), null, 0L, null); @@ -206,7 +206,7 @@ void blamePickNotFoundBlameType() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); BlamePickDto blamePickDto = new BlamePickDto(pick.getId(), null, 0L, null); @@ -227,7 +227,7 @@ void blamePickComment() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -273,7 +273,7 @@ void blamePickCommentEtc() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -338,7 +338,7 @@ void blamePickCommentNotFoundPickComment() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); BlamePickDto blamePickDto = new BlamePickDto(pick.getId(), 0L, 0L, null); @@ -360,7 +360,7 @@ void blamePickCommentPickIsNotApproval(ContentStatus contentStatus) { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", contentStatus, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", contentStatus, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -385,7 +385,7 @@ void blamePickCommentIsDeleted() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 삭제 상태의 픽픽픽 댓글 생성 @@ -411,7 +411,7 @@ void blamePickCommentNotFoundBlameType() { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -439,8 +439,9 @@ private PickComment createPickComment(Pick pick, Member createdBy, String conten return pickComment; } - private Pick createPick(String title, ContentStatus contentStatus, Count commentTotalCount) { + private Pick createPick(Member member, String title, ContentStatus contentStatus, Count commentTotalCount) { return Pick.builder() + .member(member) .title(new Title(title)) .contentStatus(contentStatus) .commentTotalCount(commentTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/common/MemberBlameServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/common/MemberBlameServiceTest.java index 75eedcc4..200b75c0 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/common/MemberBlameServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/common/MemberBlameServiceTest.java @@ -148,7 +148,7 @@ void blameAlreadyExistBlamePick() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 신고 종류 생성 @@ -183,7 +183,7 @@ void blameAlreadyExistBlamePickComment() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -265,7 +265,7 @@ void blamePick() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 신고 종류 생성 @@ -313,7 +313,7 @@ void blamePickComment() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -513,8 +513,9 @@ private PickComment createPickComment(Pick pick, Member createdBy, String conten return pickComment; } - private Pick createPick(String title, ContentStatus contentStatus, Count commentTotalCount) { + private Pick createPick(Member member, String title, ContentStatus contentStatus, Count commentTotalCount) { return Pick.builder() + .member(member) .title(new Title(title)) .contentStatus(contentStatus) .commentTotalCount(commentTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberServiceTest.java index f1d8ed7e..23c19471 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/member/MemberServiceTest.java @@ -5,10 +5,15 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.dreamypatisiel.devdevdev.domain.entity.Bookmark; +import com.dreamypatisiel.devdevdev.domain.entity.Company; import com.dreamypatisiel.devdevdev.domain.entity.Member; import com.dreamypatisiel.devdevdev.domain.entity.Pick; +import com.dreamypatisiel.devdevdev.domain.entity.PickComment; import com.dreamypatisiel.devdevdev.domain.entity.PickOption; import com.dreamypatisiel.devdevdev.domain.entity.PickVote; import com.dreamypatisiel.devdevdev.domain.entity.SurveyAnswer; @@ -17,6 +22,9 @@ import com.dreamypatisiel.devdevdev.domain.entity.SurveyVersion; import com.dreamypatisiel.devdevdev.domain.entity.SurveyVersionQuestionMapper; import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; +import com.dreamypatisiel.devdevdev.domain.entity.TechComment; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.CommentContents; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CustomSurveyAnswer; import com.dreamypatisiel.devdevdev.domain.entity.embedded.PickOptionContents; @@ -25,8 +33,9 @@ import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; -import com.dreamypatisiel.devdevdev.domain.repository.techArticle.BookmarkRepository; +import com.dreamypatisiel.devdevdev.domain.repository.CompanyRepository; import com.dreamypatisiel.devdevdev.domain.repository.member.MemberRepository; +import com.dreamypatisiel.devdevdev.domain.repository.pick.PickCommentRepository; import com.dreamypatisiel.devdevdev.domain.repository.pick.PickOptionRepository; import com.dreamypatisiel.devdevdev.domain.repository.pick.PickRepository; import com.dreamypatisiel.devdevdev.domain.repository.pick.PickVoteRepository; @@ -35,26 +44,37 @@ import com.dreamypatisiel.devdevdev.domain.repository.survey.SurveyQuestionRepository; import com.dreamypatisiel.devdevdev.domain.repository.survey.SurveyVersionQuestionMapperRepository; import com.dreamypatisiel.devdevdev.domain.repository.survey.SurveyVersionRepository; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.BookmarkRepository; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechArticleRepository; -import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyQuestionOptionResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyQuestionResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.pick.MyPickMainResponse; -import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.TechArticleMainResponse; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechCommentRepository; import com.dreamypatisiel.devdevdev.elastic.domain.service.ElasticsearchSupportTest; import com.dreamypatisiel.devdevdev.exception.MemberException; import com.dreamypatisiel.devdevdev.exception.SurveyException; import com.dreamypatisiel.devdevdev.global.common.MemberProvider; import com.dreamypatisiel.devdevdev.global.security.oauth2.model.SocialMemberDto; import com.dreamypatisiel.devdevdev.global.security.oauth2.model.UserPrincipal; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentFilter; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentRequest; import com.dreamypatisiel.devdevdev.web.dto.request.member.RecordMemberExitSurveyAnswerRequest; import com.dreamypatisiel.devdevdev.web.dto.request.member.RecordMemberExitSurveyQuestionOptionsRequest; +import com.dreamypatisiel.devdevdev.web.dto.response.comment.MyWrittenCommentResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyQuestionOptionResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyQuestionResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.member.MemberExitSurveyResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.pick.MyPickMainResponse; +import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.TechArticleMainResponse; import jakarta.persistence.EntityManager; +import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; +import org.assertj.core.groups.Tuple; 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.data.auditing.AuditingHandler; +import org.springframework.data.auditing.DateTimeProvider; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -102,6 +122,12 @@ class MemberServiceTest extends ElasticsearchSupportTest { SurveyQuestionOptionRepository surveyQuestionOptionRepository; @Autowired SurveyAnswerRepository surveyAnswerRepository; + @Autowired + CompanyRepository companyRepository; + @Autowired + TechCommentRepository techCommentRepository; + @Autowired + PickCommentRepository pickCommentRepository; @Test @DisplayName("회원이 회원탈퇴 설문조사를 완료하지 않으면 탈퇴가 불가능하다.") @@ -519,6 +545,579 @@ void recordMemberExitSurveyAnswerMemberException() { .hasMessage(INVALID_MEMBER_NOT_FOUND_MESSAGE); } + @Test + @DisplayName("회원이 작성한 픽픽픽, 기술블로그 댓글을 작성시간 내림차순으로 무한스크롤 방식으로 조회한다.") + void findMyWrittenComments_ALL() { + // given + DateTimeProvider dateTimeProvider = mock(DateTimeProvider.class); + AuditingHandler auditingHandler = mock(AuditingHandler.class); + auditingHandler.setDateTimeProvider(dateTimeProvider); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0))); + + // 회원 생성 + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + UserPrincipal userPrincipal = UserPrincipal.createByMember(member); + SecurityContext context = SecurityContextHolder.getContext(); + context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), + userPrincipal.getSocialType().name())); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + // 픽픽픽 생성 + Pick pick = createPick("픽픽픽", member); + pickRepository.save(pick); + + // 픽픽픽 옵션 생성 + PickOption pickOption = createPickOption(pick, "픽픽픽 A", PickOptionType.firstPickOption); + pickOptionRepository.save(pickOption); + + // 픽픽픽 투표 생성 + PickVote pickVote = createPickVote(pick, pickOption, member); + pickVoteRepository.save(pickVote); + + // 픽픽픽 댓글 생성 + PickComment pickComment1 = createPickComment(pick, member, pickVote, null, null, "픽픽픽 댓글1", true, 0L); + PickComment pickComment2 = createPickComment(pick, member, null, pickComment1, pickComment1, "픽픽픽 댓글2", false, + 1L); + PickComment pickComment3 = createPickComment(pick, member, null, pickComment1, pickComment2, "픽픽픽 댓글3", false, + 2L); + PickComment pickComment4 = createPickComment(pick, member, null, pickComment1, pickComment3, "픽픽픽 댓글4", false, + 3L); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 2, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 3, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment3); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 4, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment4); + + // 기술블로그 회사 생성 + Company company = createCompany("DreamyPatisiel"); + companyRepository.save(company); + + // 기술블로그 생성 + TechArticle techArticle = createTechArticle(company, "기술블로그 제목"); + techArticleRepository.save(techArticle); + + // 기술블로그 댓글 생성 + TechComment techComment1 = createTechComment(techArticle, member, null, null, "기술블로그 댓글1", 0L); + TechComment techComment2 = createTechComment(techArticle, member, techComment1, techComment1, "기술블로그 댓글2", 1L); + TechComment techComment3 = createTechComment(techArticle, member, techComment1, techComment2, "기술블로그 댓글3", 2L); + TechComment techComment4 = createTechComment(techArticle, member, techComment1, techComment3, "기술블로그 댓글4", 3L); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 5, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 6, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 7, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment3); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 8, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment4); + + Pageable pageable = PageRequest.of(0, 6); + + // 첫 번째 페이지 + // when1 + Long techCommentId = techComment4.getId() + 1L; + Long pickCommentId = pickComment4.getId() + 1L; + + MyWrittenCommentRequest myWrittenCommentRequest = new MyWrittenCommentRequest(pickCommentId, techCommentId, + MyWrittenCommentFilter.ALL); + + SliceCustom page1 = memberService.findMyWrittenComments(pageable, + myWrittenCommentRequest, authentication); + + // then1 + assertAll( + () -> assertThat(page1.getTotalElements()).isEqualTo(8), + () -> assertThat(page1.hasNext()).isEqualTo(true) + ); + + assertThat(page1.getContent()).hasSize(6) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "commentRecommendTotalCount", "pickOptionTitle", "pickOptionType") + .containsExactly( + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment4.getId(), + "TECH_ARTICLE", techComment4.getContents().getCommentContents(), + techComment4.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment3.getId(), + "TECH_ARTICLE", techComment3.getContents().getCommentContents(), + techComment3.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment2.getId(), + "TECH_ARTICLE", techComment2.getContents().getCommentContents(), + techComment2.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment1.getId(), + "TECH_ARTICLE", techComment1.getContents().getCommentContents(), + techComment1.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment4.getId(), + "PICK", pickComment4.getContents().getCommentContents(), + pickComment4.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment3.getId(), + "PICK", pickComment3.getContents().getCommentContents(), + pickComment3.getRecommendTotalCount().getCount(), + null, null) + ); + + // 두 번째 페이지 + // when2 + techCommentId = techComment1.getId(); + pickCommentId = pickComment3.getId(); + + MyWrittenCommentRequest myWrittenCommentRequest2 = new MyWrittenCommentRequest(pickCommentId, techCommentId, + MyWrittenCommentFilter.ALL); + + SliceCustom page2 = memberService.findMyWrittenComments(pageable, + myWrittenCommentRequest2, authentication); + + // then2 + assertAll( + () -> assertThat(page2.getTotalElements()).isEqualTo(8), + () -> assertThat(page2.hasNext()).isEqualTo(false) + ); + + assertThat(page2.getContent()).hasSize(2) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "commentRecommendTotalCount", "pickOptionTitle", "pickOptionType") + .containsExactly( + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment2.getId(), + "PICK", pickComment2.getContents().getCommentContents(), + pickComment2.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment1.getId(), + "PICK", pickComment1.getContents().getCommentContents(), + pickComment1.getRecommendTotalCount().getCount(), + pickOption.getTitle().getTitle(), pickOption.getPickOptionType().name()) + ); + } + + @Test + @DisplayName("픽픽픽, 기술블로그 댓글을 작성시간 내림차순으로 무한스크롤 방식으로 조회할 때 회원이 아니면 예외가 발생한다.") + void findMyWrittenComments_INVALID_MEMBER_NOT_FOUND_MESSAGE() { + // given + UserPrincipal userPrincipal = UserPrincipal.createByEmailAndRoleAndSocialType(email, role, socialType); + SecurityContext context = SecurityContextHolder.getContext(); + context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), + userPrincipal.getSocialType().name())); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + Pageable pageable = PageRequest.of(0, 6); + MyWrittenCommentRequest myWrittenCommentRequest = new MyWrittenCommentRequest(0L, 0L, + MyWrittenCommentFilter.ALL); + + // when // then + assertThatThrownBy(() -> memberService.findMyWrittenComments(pageable, myWrittenCommentRequest, authentication)) + .isInstanceOf(MemberException.class) + .hasMessage(INVALID_MEMBER_NOT_FOUND_MESSAGE); + } + + @Test + @DisplayName("회원이 작성한 픽픽픽 댓글을 작성시간 내림차순으로 무한스크롤 방식으로 조회한다.") + void findMyWrittenComments_PICK() { + // given + DateTimeProvider dateTimeProvider = mock(DateTimeProvider.class); + AuditingHandler auditingHandler = mock(AuditingHandler.class); + auditingHandler.setDateTimeProvider(dateTimeProvider); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0, 0, 0))); + + // 회원 생성 + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + UserPrincipal userPrincipal = UserPrincipal.createByMember(member); + SecurityContext context = SecurityContextHolder.getContext(); + context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), + userPrincipal.getSocialType().name())); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + // 픽픽픽 생성 + Pick pick = createPick("픽픽픽", member); + pickRepository.save(pick); + + // 픽픽픽 옵션 생성 + PickOption pickOption = createPickOption(pick, "픽픽픽 A", PickOptionType.firstPickOption); + pickOptionRepository.save(pickOption); + + // 픽픽픽 투표 생성 + PickVote pickVote = createPickVote(pick, pickOption, member); + pickVoteRepository.save(pickVote); + + // 픽픽픽 댓글 생성 + PickComment pickComment1 = createPickComment(pick, member, pickVote, null, null, "픽픽픽 댓글1", true, 0L); + PickComment pickComment2 = createPickComment(pick, member, null, pickComment1, pickComment1, "픽픽픽 댓글2", false, + 1L); + PickComment pickComment3 = createPickComment(pick, member, null, pickComment1, pickComment2, "픽픽픽 댓글3", false, + 2L); + PickComment pickComment4 = createPickComment(pick, member, null, pickComment1, pickComment3, "픽픽픽 댓글4", false, + 3L); + PickComment pickComment5 = createPickComment(pick, member, null, pickComment1, pickComment4, "픽픽픽 댓글5", false, + 4L); + PickComment pickComment6 = createPickComment(pick, member, null, pickComment1, pickComment5, "픽픽픽 댓글6", false, + 5L); + PickComment pickComment7 = createPickComment(pick, member, null, pickComment1, pickComment6, "픽픽픽 댓글7", false, + 6L); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 2, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 3, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment3); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 4, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment4); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 5, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment5); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 6, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment6); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 7, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment7); + + // 기술블로그 회사 생성 + Company company = createCompany("DreamyPatisiel"); + companyRepository.save(company); + + // 기술블로그 생성 + TechArticle techArticle = createTechArticle(company, "기술블로그 제목"); + techArticleRepository.save(techArticle); + + // 기술블로그 댓글 생성 + TechComment techComment1 = createTechComment(techArticle, member, null, null, "기술블로그 댓글1", 0L); + TechComment techComment2 = createTechComment(techArticle, member, techComment1, techComment1, "기술블로그 댓글2", 1L); + TechComment techComment3 = createTechComment(techArticle, member, techComment1, techComment2, "기술블로그 댓글3", 2L); + TechComment techComment4 = createTechComment(techArticle, member, techComment1, techComment3, "기술블로그 댓글4", 3L); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 5, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 6, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 7, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment3); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 8, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment4); + + Pageable pageable = PageRequest.of(0, 6); + + // 첫 번째 페이지 + Long techCommentId = techComment4.getId() + 1L; + Long pickCommentId = pickComment7.getId() + 1L; + + MyWrittenCommentRequest myWrittenCommentRequest1 = new MyWrittenCommentRequest(pickCommentId, techCommentId, + MyWrittenCommentFilter.PICK); + + SliceCustom page1 = memberService.findMyWrittenComments(pageable, + myWrittenCommentRequest1, authentication); + + // then + assertAll( + () -> assertThat(page1.getTotalElements()).isEqualTo(7), + () -> assertThat(page1.hasNext()).isEqualTo(true) + ); + + assertThat(page1.getContent()).hasSize(6) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "commentRecommendTotalCount", "pickOptionTitle", "pickOptionType") + .containsExactly( + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment7.getId(), + "PICK", pickComment7.getContents().getCommentContents(), + pickComment7.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment6.getId(), + "PICK", pickComment6.getContents().getCommentContents(), + pickComment6.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment5.getId(), + "PICK", pickComment5.getContents().getCommentContents(), + pickComment5.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment4.getId(), + "PICK", pickComment4.getContents().getCommentContents(), + pickComment4.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment3.getId(), + "PICK", pickComment3.getContents().getCommentContents(), + pickComment3.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment2.getId(), + "PICK", pickComment2.getContents().getCommentContents(), + pickComment2.getRecommendTotalCount().getCount(), + null, null) + ); + + pickCommentId = pickComment2.getId(); + + MyWrittenCommentRequest myWrittenCommentRequest2 = new MyWrittenCommentRequest(pickCommentId, techCommentId, + MyWrittenCommentFilter.PICK); + + SliceCustom page2 = memberService.findMyWrittenComments(pageable, + myWrittenCommentRequest2, authentication); + + // then + assertAll( + () -> assertThat(page2.getTotalElements()).isEqualTo(7), + () -> assertThat(page2.hasNext()).isEqualTo(false) + ); + + assertThat(page2.getContent()).hasSize(1) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "commentRecommendTotalCount", "pickOptionTitle", "pickOptionType") + .containsExactly( + Tuple.tuple(pick.getId(), pick.getTitle().getTitle(), pickComment1.getId(), + "PICK", pickComment1.getContents().getCommentContents(), + pickComment1.getRecommendTotalCount().getCount(), + pickOption.getTitle().getTitle(), pickOption.getPickOptionType().name()) + ); + } + + @Test + @DisplayName("회원이 작성한 기술블로그 댓글을 작성시간 내림차순으로 무한스크롤 방식으로 조회한다.") + void findMyWrittenComments_TECH() { + // given + DateTimeProvider dateTimeProvider = mock(DateTimeProvider.class); + AuditingHandler auditingHandler = mock(AuditingHandler.class); + auditingHandler.setDateTimeProvider(dateTimeProvider); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0, 0, 0))); + + // 회원 생성 + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + UserPrincipal userPrincipal = UserPrincipal.createByMember(member); + SecurityContext context = SecurityContextHolder.getContext(); + context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), + userPrincipal.getSocialType().name())); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + // 픽픽픽 생성 + Pick pick = createPick("픽픽픽", member); + pickRepository.save(pick); + + // 픽픽픽 옵션 생성 + PickOption pickOption = createPickOption(pick, "픽픽픽 A", PickOptionType.firstPickOption); + pickOptionRepository.save(pickOption); + + // 픽픽픽 투표 생성 + PickVote pickVote = createPickVote(pick, pickOption, member); + pickVoteRepository.save(pickVote); + + // 픽픽픽 댓글 생성 + PickComment pickComment1 = createPickComment(pick, member, pickVote, null, null, "픽픽픽 댓글1", true, 0L); + PickComment pickComment2 = createPickComment(pick, member, null, pickComment1, pickComment1, "픽픽픽 댓글2", false, + 1L); + PickComment pickComment3 = createPickComment(pick, member, null, pickComment1, pickComment2, "픽픽픽 댓글3", false, + 2L); + PickComment pickComment4 = createPickComment(pick, member, null, pickComment1, pickComment3, "픽픽픽 댓글4", false, + 3L); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 1, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 2, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 3, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment3); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 4, 1, 0, 0, 0, 0))); + pickCommentRepository.save(pickComment4); + + // 기술블로그 회사 생성 + Company company = createCompany("DreamyPatisiel"); + companyRepository.save(company); + + // 기술블로그 생성 + TechArticle techArticle = createTechArticle(company, "기술블로그 제목"); + techArticleRepository.save(techArticle); + + // 기술블로그 댓글 생성 + TechComment techComment1 = createTechComment(techArticle, member, null, null, "기술블로그 댓글1", 0L); + TechComment techComment2 = createTechComment(techArticle, member, techComment1, techComment1, "기술블로그 댓글2", 1L); + TechComment techComment3 = createTechComment(techArticle, member, techComment1, techComment2, "기술블로그 댓글3", 2L); + TechComment techComment4 = createTechComment(techArticle, member, techComment1, techComment3, "기술블로그 댓글4", 3L); + TechComment techComment5 = createTechComment(techArticle, member, techComment1, techComment4, "기술블로그 댓글5", 4L); + TechComment techComment6 = createTechComment(techArticle, member, techComment1, techComment5, "기술블로그 댓글6", 5L); + TechComment techComment7 = createTechComment(techArticle, member, techComment1, techComment6, "기술블로그 댓글7", 6L); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 5, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment1); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 6, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment2); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 7, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment3); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 8, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment4); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 9, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment5); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 10, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment6); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2024, 11, 1, 0, 0, 0, 0))); + techCommentRepository.save(techComment7); + + Pageable pageable = PageRequest.of(0, 6); + + // 첫 번째 페이지 + // when1 + Long techCommentId = techComment7.getId() + 1L; + Long pickCommentId = pickComment4.getId() + 1L; + + MyWrittenCommentRequest myWrittenCommentRequest1 = new MyWrittenCommentRequest(pickCommentId, techCommentId, + MyWrittenCommentFilter.TECH_ARTICLE); + + SliceCustom page1 = memberService.findMyWrittenComments(pageable, + myWrittenCommentRequest1, authentication); + + // then1 + assertAll( + () -> assertThat(page1.getTotalElements()).isEqualTo(7), + () -> assertThat(page1.hasNext()).isEqualTo(true) + ); + + assertThat(page1.getContent()).hasSize(6) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "commentRecommendTotalCount", "pickOptionTitle", "pickOptionType") + .containsExactly( + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment7.getId(), + "TECH_ARTICLE", techComment7.getContents().getCommentContents(), + techComment7.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment6.getId(), + "TECH_ARTICLE", techComment6.getContents().getCommentContents(), + techComment6.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment5.getId(), + "TECH_ARTICLE", techComment5.getContents().getCommentContents(), + techComment5.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment4.getId(), + "TECH_ARTICLE", techComment4.getContents().getCommentContents(), + techComment4.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment3.getId(), + "TECH_ARTICLE", techComment3.getContents().getCommentContents(), + techComment3.getRecommendTotalCount().getCount(), + null, null), + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment2.getId(), + "TECH_ARTICLE", techComment2.getContents().getCommentContents(), + techComment2.getRecommendTotalCount().getCount(), + null, null) + ); + + // 두 번째 페이지 + // when2 + techCommentId = techComment2.getId(); + + MyWrittenCommentRequest myWrittenCommentRequest2 = new MyWrittenCommentRequest(pickCommentId, techCommentId, + MyWrittenCommentFilter.TECH_ARTICLE); + + SliceCustom page2 = memberService.findMyWrittenComments(pageable, + myWrittenCommentRequest2, authentication); + + // then2 + assertAll( + () -> assertThat(page2.getTotalElements()).isEqualTo(7), + () -> assertThat(page2.hasNext()).isEqualTo(false) + ); + + assertThat(page2.getContent()).hasSize(1) + .extracting("postId", "postTitle", "commentId", "commentType", "commentContents", + "commentRecommendTotalCount", "pickOptionTitle", "pickOptionType") + .containsExactly( + Tuple.tuple(techArticle.getId(), techArticle.getTitle().getTitle(), techComment1.getId(), + "TECH_ARTICLE", techComment1.getContents().getCommentContents(), + techComment1.getRecommendTotalCount().getCount(), + null, null) + ); + } + + private static TechComment createTechComment(TechArticle techArticle, Member member, TechComment originParent, + TechComment parent, String contents, Long recommendTotalCount) { + return TechComment.builder() + .techArticle(techArticle) + .createdBy(member) + .originParent(originParent) + .parent(parent) + .contents(new CommentContents(contents)) + .recommendTotalCount(new Count(recommendTotalCount)) + .build(); + } + + private static TechArticle createTechArticle(Company company, String title) { + return TechArticle.builder() + .company(company) + .title(new Title(title)) + .build(); + } + + private static Company createCompany(String companyName) { + return Company.builder() + .name(new CompanyName(companyName)) + .build(); + } + + private static PickOption createPickOption(Pick pick, String title, PickOptionType pickOptionType) { + return PickOption.builder() + .pick(pick) + .title(new Title(title)) + .pickOptionType(pickOptionType) + .build(); + } + + private static Pick createPick(String title, Member member) { + return Pick.builder() + .title(new Title(title)) + .member(member) + .contentStatus(ContentStatus.APPROVAL) + .build(); + } + + private static PickComment createPickComment(Pick pick, Member member, PickVote pickVote, PickComment originParent, + PickComment parent, String contents, Boolean isPublic, + Long recommendTotalCount) { + return PickComment.builder() + .pick(pick) + .createdBy(member) + .pickVote(pickVote) + .originParent(originParent) + .parent(parent) + .contents(new CommentContents(contents)) + .isPublic(isPublic) + .recommendTotalCount(new Count(recommendTotalCount)) + .build(); + } + private Long pickSetup(Member member, ContentStatus contentStatus, Title pickTitle, Title firstPickOptionTitle, PickOptionContents firstPickOptionContents, Title secondPickOptinTitle, PickOptionContents secondPickOptionContents) { diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/GuestPickServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/GuestPickServiceTest.java index 4581a337..eca4d2c4 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/GuestPickServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/GuestPickServiceTest.java @@ -112,13 +112,16 @@ class GuestPickServiceTest { @DisplayName("익명 회원이 커서 방식으로 익명 회원 전용 픽픽픽 메인을 조회한다.") void findPicksMain() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + Count pickVoteTotalCount = new Count(pickOptionVoteCount1.getCount() + pickOptionVoteCount2.getCount()); Count pickViewTotalCount = new Count(1); Count pickCommentTotalCount = new Count(0); Count pickPopularScore = new Count(0); - Pick pick = createPick(pickTitle, pickVoteTotalCount, pickViewTotalCount, pickCommentTotalCount, - pickPopularScore, - thumbnailUrl, author, List.of()); + Pick pick = createPick(member, pickTitle, pickVoteTotalCount, pickViewTotalCount, pickCommentTotalCount, + pickPopularScore, thumbnailUrl, author, List.of()); pickRepository.save(pick); PickOption pickOption1 = createPickOption(pick, pickOptionTitle1, pickOptionContents1, pickOptionVoteCount1, @@ -161,6 +164,10 @@ void findPicksMain() { @DisplayName("익명 회원이 커서 방식으로 익명 회원 전용 조회수 내림차순으로 픽픽픽 메인을 조회한다.") void findPicksMainMOST_VIEWED() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); Title title3 = new Title("픽3타이틀"); @@ -170,9 +177,12 @@ void findPicksMainMOST_VIEWED() { Count pick3ViewTotalCount = new Count(3); Count count = new Count(0); - Pick pick1 = createPick(title1, count, pick1ViewTotalCount, count, count, thumbnailUrl, author, List.of()); - Pick pick2 = createPick(title2, count, pick2ViewTotalCount, count, count, thumbnailUrl, author, List.of()); - Pick pick3 = createPick(title3, count, pick3ViewTotalCount, count, count, thumbnailUrl, author, List.of()); + Pick pick1 = createPick(member, title1, count, pick1ViewTotalCount, count, count, thumbnailUrl, author, + List.of()); + Pick pick2 = createPick(member, title2, count, pick2ViewTotalCount, count, count, thumbnailUrl, author, + List.of()); + Pick pick3 = createPick(member, title3, count, pick3ViewTotalCount, count, count, thumbnailUrl, author, + List.of()); pickRepository.saveAll(List.of(pick1, pick2, pick3)); PickOption pickOption1 = createPickOption(pick1, new Title("픽옵션1"), new PickOptionContents("픽콘텐츠1"), @@ -215,14 +225,18 @@ void findPicksMainMOST_VIEWED() { @DisplayName("익명 회원이 커서 방식으로 익명 회원 전용 생성시간 내림차순으로 픽픽픽 메인을 조회한다.") void findPicksMainLATEST() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); Title title3 = new Title("픽3타이틀"); Count count = new Count(0); - Pick pick1 = createPick(title1, count, count, count, count, thumbnailUrl, author, List.of()); - Pick pick2 = createPick(title2, count, count, count, count, thumbnailUrl, author, List.of()); - Pick pick3 = createPick(title3, count, count, count, count, thumbnailUrl, author, List.of()); + Pick pick1 = createPick(member, title1, count, count, count, count, thumbnailUrl, author, List.of()); + Pick pick2 = createPick(member, title2, count, count, count, count, thumbnailUrl, author, List.of()); + Pick pick3 = createPick(member, title3, count, count, count, count, thumbnailUrl, author, List.of()); pickRepository.saveAll(List.of(pick1, pick2, pick3)); PickOption pickOption1 = createPickOption(pick1, new Title("픽옵션1"), new PickOptionContents("픽콘텐츠1"), @@ -265,6 +279,9 @@ void findPicksMainLATEST() { @DisplayName("익명 회원가 커서 방식으로 익명 회원 전용 댓글수 내림차순으로 픽픽픽 메인을 조회한다.") void findPicksMainMOST_COMMENTED() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); @@ -274,9 +291,12 @@ void findPicksMainMOST_COMMENTED() { Count pick3commentTotalCount = new Count(3); Count count = new Count(0); - Pick pick1 = createPick(title1, count, count, pick1commentTotalCount, count, thumbnailUrl, author, List.of()); - Pick pick2 = createPick(title2, count, count, pick2commentTotalCount, count, thumbnailUrl, author, List.of()); - Pick pick3 = createPick(title3, count, count, pick3commentTotalCount, count, thumbnailUrl, author, List.of()); + Pick pick1 = createPick(member, title1, count, count, pick1commentTotalCount, count, thumbnailUrl, author, + List.of()); + Pick pick2 = createPick(member, title2, count, count, pick2commentTotalCount, count, thumbnailUrl, author, + List.of()); + Pick pick3 = createPick(member, title3, count, count, pick3commentTotalCount, count, thumbnailUrl, author, + List.of()); pickRepository.saveAll(List.of(pick1, pick2, pick3)); PickOption pickOption1 = createPickOption(pick1, new Title("픽옵션1"), new PickOptionContents("픽콘텐츠1"), @@ -321,6 +341,10 @@ void findPicksMainMOST_COMMENTED() { + ", 조회수:" + PickPopularScorePolicy.VIEW_WEIGHT + ")") void findPicksMainPOPULAR() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); Title title3 = new Title("픽3타이틀"); @@ -337,15 +361,15 @@ void findPicksMainPOPULAR() { Count pick3VoteTotalCount = new Count(1); Count pick3ViewTotalCount = new Count(2); - Pick pick1 = createPick(title1, pick1VoteTotalCount, pick1ViewTotalCount, pick1commentTotalCount, + Pick pick1 = createPick(member, title1, pick1VoteTotalCount, pick1ViewTotalCount, pick1commentTotalCount, thumbnailUrl, author, List.of()); pick1.changePopularScore(pickPopularScorePolicy); - Pick pick2 = createPick(title2, pick2VoteTotalCount, pick2ViewTotalCount, pick2commentTotalCount, + Pick pick2 = createPick(member, title2, pick2VoteTotalCount, pick2ViewTotalCount, pick2commentTotalCount, thumbnailUrl, author, List.of()); pick2.changePopularScore(pickPopularScorePolicy); - Pick pick3 = createPick(title3, pick3VoteTotalCount, pick3ViewTotalCount, pick3commentTotalCount, + Pick pick3 = createPick(member, title3, pick3VoteTotalCount, pick3ViewTotalCount, pick3commentTotalCount, thumbnailUrl, author, List.of()); pick3.changePopularScore(pickPopularScorePolicy); @@ -929,12 +953,13 @@ private PickOptionImage createPickOptionImage(String name, String imageUrl, Pick return pickOptionImage; } - private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTotalCount, + private Pick createPick(Member member, Title title, Count pickVoteTotalCount, Count pickViewTotalCount, Count pickcommentTotalCount, Count pickPopularScore, String thumbnailUrl, String author, List pickVotes ) { Pick pick = Pick.builder() + .member(member) .title(title) .voteTotalCount(pickVoteTotalCount) .viewTotalCount(pickViewTotalCount) @@ -950,12 +975,13 @@ private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTot return pick; } - private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTotalCount, + private Pick createPick(Member member, Title title, Count pickVoteTotalCount, Count pickViewTotalCount, Count pickcommentTotalCount, String thumbnailUrl, String author, List pickVotes ) { Pick pick = Pick.builder() + .member(member) .title(title) .voteTotalCount(pickVoteTotalCount) .viewTotalCount(pickViewTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/MemberPickServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/MemberPickServiceTest.java index 04ea86c8..9493a32a 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/MemberPickServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/pick/MemberPickServiceTest.java @@ -163,7 +163,7 @@ void findPicksMain() { Count pickPopularScore = new Count(0); String thumbnailUrl = "섬네일 이미지 url"; String author = "운영자"; - Pick pick = createPick(pickTitle, pickVoteTotalCount, pickViewTotalCount, pickCommentTotalCount, + Pick pick = createPick(member, pickTitle, pickVoteTotalCount, pickViewTotalCount, pickCommentTotalCount, pickPopularScore, thumbnailUrl, author, ContentStatus.APPROVAL); pick.changePopularScore(pickPopularScorePolicy); pickRepository.save(pick); @@ -208,6 +208,9 @@ void findPicksMain() { @DisplayName("회원이 커서 방식으로 회원 전용 조회수 내림차순으로 픽픽픽 메인을 조회한다.") void findPicksMainMOST_VIEWED() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); @@ -220,22 +223,18 @@ void findPicksMainMOST_VIEWED() { Count pick4ViewTotalCount = new Count(4); Count count = new Count(1); - Pick pick1 = createPick(title1, count, pick1ViewTotalCount, count, count, thumbnailUrl, author, + Pick pick1 = createPick(member, title1, count, pick1ViewTotalCount, count, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick2 = createPick(title2, count, pick2ViewTotalCount, count, count, thumbnailUrl, author, + Pick pick2 = createPick(member, title2, count, pick2ViewTotalCount, count, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick3 = createPick(title3, count, pick3ViewTotalCount, count, count, thumbnailUrl, author, + Pick pick3 = createPick(member, title3, count, pick3ViewTotalCount, count, count, thumbnailUrl, author, ContentStatus.REJECT); - Pick pick4 = createPick(title4, count, pick4ViewTotalCount, count, count, thumbnailUrl, author, + Pick pick4 = createPick(member, title4, count, pick4ViewTotalCount, count, count, thumbnailUrl, author, ContentStatus.READY); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4)); Pageable pageable = PageRequest.of(0, 10); - SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); - Member member = Member.createMemberBy(socialMemberDto); - memberRepository.save(member); - UserPrincipal userPrincipal = UserPrincipal.createByMember(member); SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), @@ -259,25 +258,28 @@ void findPicksMainMOST_VIEWED() { @DisplayName("회원이 커서 방식으로 익명 사용자 전용 생성시간 내림차순으로 픽픽픽 메인을 조회한다.") void findPicksMainLATEST() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); Title title3 = new Title("픽3타이틀"); Title title4 = new Title("픽4타이틀"); Count count = new Count(1); - Pick pick1 = createPick(title1, count, count, count, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick2 = createPick(title2, count, count, count, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick3 = createPick(title3, count, count, count, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick4 = createPick(title4, count, count, count, count, thumbnailUrl, author, ContentStatus.READY); - Pick pick5 = createPick(title4, count, count, count, count, thumbnailUrl, author, ContentStatus.REJECT); + Pick pick1 = createPick(member, title1, count, count, count, count, thumbnailUrl, author, + ContentStatus.APPROVAL); + Pick pick2 = createPick(member, title2, count, count, count, count, thumbnailUrl, author, + ContentStatus.APPROVAL); + Pick pick3 = createPick(member, title3, count, count, count, count, thumbnailUrl, author, + ContentStatus.APPROVAL); + Pick pick4 = createPick(member, title4, count, count, count, count, thumbnailUrl, author, ContentStatus.READY); + Pick pick5 = createPick(member, title4, count, count, count, count, thumbnailUrl, author, ContentStatus.REJECT); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5)); Pageable pageable = PageRequest.of(0, 10); - SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); - Member member = Member.createMemberBy(socialMemberDto); - memberRepository.save(member); - UserPrincipal userPrincipal = UserPrincipal.createByMember(member); SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), @@ -302,6 +304,10 @@ void findPicksMainLATEST() { @DisplayName("회원이 커서 방식으로 익명 사용자 전용 댓글수 내림차순으로 픽픽픽 메인을 조회한다.") void findPicksMainMOST_COMMENTED() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); Title title3 = new Title("픽3타이틀"); @@ -312,24 +318,20 @@ void findPicksMainMOST_COMMENTED() { Count pick5commentTotalCount = new Count(5); Count count = new Count(1); - Pick pick1 = createPick(title1, count, count, pick1commentTotalCount, count, thumbnailUrl, author, + Pick pick1 = createPick(member, title1, count, count, pick1commentTotalCount, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick2 = createPick(title2, count, count, pick2commentTotalCount, count, thumbnailUrl, author, + Pick pick2 = createPick(member, title2, count, count, pick2commentTotalCount, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick3 = createPick(title3, count, count, pick3commentTotalCount, count, thumbnailUrl, author, + Pick pick3 = createPick(member, title3, count, count, pick3commentTotalCount, count, thumbnailUrl, author, ContentStatus.APPROVAL); - Pick pick4 = createPick(title3, count, count, pick4commentTotalCount, count, thumbnailUrl, author, + Pick pick4 = createPick(member, title3, count, count, pick4commentTotalCount, count, thumbnailUrl, author, ContentStatus.READY); - Pick pick5 = createPick(title3, count, count, pick5commentTotalCount, count, thumbnailUrl, author, + Pick pick5 = createPick(member, title3, count, count, pick5commentTotalCount, count, thumbnailUrl, author, ContentStatus.REJECT); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5)); Pageable pageable = PageRequest.of(0, 10); - SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); - Member member = Member.createMemberBy(socialMemberDto); - memberRepository.save(member); - UserPrincipal userPrincipal = UserPrincipal.createByMember(member); SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), @@ -357,6 +359,10 @@ void findPicksMainMOST_COMMENTED() { + ", 조회수:" + PickPopularScorePolicy.VIEW_WEIGHT + ")") void findPicksMainPOPULAR() { // given + SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + Title title1 = new Title("픽1타이틀"); Title title2 = new Title("픽2타이틀"); Title title3 = new Title("픽3타이틀"); @@ -373,33 +379,34 @@ void findPicksMainPOPULAR() { Count pick3VoteTotalCount = new Count(1); Count pick3ViewTotalCount = new Count(2); - Pick pick1 = createPick(new Title("픽1타이틀"), pick1VoteTotalCount, pick1ViewTotalCount, pick1commentTotalCount, + Pick pick1 = createPick(member, new Title("픽1타이틀"), pick1VoteTotalCount, pick1ViewTotalCount, + pick1commentTotalCount, thumbnailUrl, author, ContentStatus.APPROVAL, List.of()); pick1.changePopularScore(pickPopularScorePolicy); - Pick pick2 = createPick(new Title("픽2타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, pick2commentTotalCount, + Pick pick2 = createPick(member, new Title("픽2타이틀"), pick2VoteTotalCount, pick2ViewTotalCount, + pick2commentTotalCount, thumbnailUrl, author, ContentStatus.APPROVAL, List.of()); pick2.changePopularScore(pickPopularScorePolicy); - Pick pick3 = createPick(new Title("픽3타이틀"), pick3VoteTotalCount, pick3ViewTotalCount, pick3commentTotalCount, + Pick pick3 = createPick(member, new Title("픽3타이틀"), pick3VoteTotalCount, pick3ViewTotalCount, + pick3commentTotalCount, thumbnailUrl, author, ContentStatus.APPROVAL, List.of()); pick3.changePopularScore(pickPopularScorePolicy); - Pick pick4 = createPick(new Title("픽4타이틀"), pick3VoteTotalCount, pick3ViewTotalCount, pick3commentTotalCount, + Pick pick4 = createPick(member, new Title("픽4타이틀"), pick3VoteTotalCount, pick3ViewTotalCount, + pick3commentTotalCount, thumbnailUrl, author, ContentStatus.READY, List.of()); pick4.changePopularScore(pickPopularScorePolicy); - Pick pick5 = createPick(new Title("픽5타이틀"), pick3VoteTotalCount, pick3ViewTotalCount, pick3commentTotalCount, + Pick pick5 = createPick(member, new Title("픽5타이틀"), pick3VoteTotalCount, pick3ViewTotalCount, + pick3commentTotalCount, thumbnailUrl, author, ContentStatus.REJECT, List.of()); pick5.changePopularScore(pickPopularScorePolicy); pickRepository.saveAll(List.of(pick1, pick2, pick3, pick4, pick5)); Pageable pageable = PageRequest.of(0, 10); - SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); - Member member = Member.createMemberBy(socialMemberDto); - memberRepository.save(member); - UserPrincipal userPrincipal = UserPrincipal.createByMember(member); SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(new OAuth2AuthenticationToken(userPrincipal, userPrincipal.getAuthorities(), @@ -1626,12 +1633,13 @@ private Pick createPick(Title title, Member member) { .build(); } - private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTotalCount, + private Pick createPick(Member member, Title title, Count pickVoteTotalCount, Count pickViewTotalCount, Count pickcommentTotalCount, Count pickPopularScore, String thumbnailUrl, String author, ContentStatus contentStatus ) { return Pick.builder() + .member(member) .title(title) .voteTotalCount(pickVoteTotalCount) .viewTotalCount(pickViewTotalCount) @@ -1643,13 +1651,14 @@ private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTot .build(); } - private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTotalCount, + private Pick createPick(Member member, Title title, Count pickVoteTotalCount, Count pickViewTotalCount, Count pickcommentTotalCount, String thumbnailUrl, String author, ContentStatus contentStatus, List pickVotes ) { Pick pick = Pick.builder() + .member(member) .title(title) .voteTotalCount(pickVoteTotalCount) .viewTotalCount(pickViewTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechArticleServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechArticleServiceTest.java index b09ff523..e20233c1 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechArticleServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechArticleServiceTest.java @@ -13,6 +13,7 @@ import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; import com.dreamypatisiel.devdevdev.domain.entity.TechArticleRecommend; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; @@ -205,7 +206,9 @@ void getTechArticleNotAnonymousUserException() { @DisplayName("익명 사용자가 기술블로그 상세를 조회할 때 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundTechArticleException() { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle( + new Title("매일 1,000만 사용자의 데이터를 꿈파는 어떻게 처리할까?"), + new Url("https://example.com"), new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -226,7 +229,9 @@ void getTechArticleNotFoundTechArticleException() { @DisplayName("익명 사용자가 기술블로그 상세를 조회할 때 엘라스틱ID가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticIdException() { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle( + new Title("매일 1,000만 사용자의 데이터를 꿈파는 어떻게 처리할까?"), + new Url("https://example.com"), new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -247,7 +252,9 @@ void getTechArticleNotFoundElasticIdException() { @DisplayName("익명 사용자가 기술블로그 상세를 조회할 때 엘라스틱 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticTechArticleException() { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle( + new Title("매일 1,000만 사용자의 데이터를 꿈파는 어떻게 처리할까?"), + new Url("https://example.com"), new Count(1L), new Count(1L), new Count(1L), new Count(1L), "elasticId", company); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechCommentServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechCommentServiceTest.java index 79d7b2e6..1618d4f7 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechCommentServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/GuestTechCommentServiceTest.java @@ -15,6 +15,7 @@ import com.dreamypatisiel.devdevdev.domain.entity.embedded.CommentContents; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; @@ -30,7 +31,6 @@ import com.dreamypatisiel.devdevdev.global.security.oauth2.model.UserPrincipal; import com.dreamypatisiel.devdevdev.global.utils.AuthenticationMemberUtils; import com.dreamypatisiel.devdevdev.web.dto.SliceCommentCustom; -import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; import com.dreamypatisiel.devdevdev.web.dto.request.techArticle.RegisterTechCommentRequest; import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.TechCommentsResponse; import com.dreamypatisiel.devdevdev.web.dto.response.techArticle.TechRepliedCommentsResponse; @@ -101,7 +101,8 @@ void registerTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); TechArticle savedTechArticle = techArticleRepository.save(techArticle); Long id = savedTechArticle.getId(); @@ -128,7 +129,8 @@ void registerRepliedTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -160,7 +162,8 @@ void recommendTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(2L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -189,7 +192,8 @@ void getTechCommentsSortByOLDEST() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -481,7 +485,8 @@ void getTechCommentsSortByLATEST() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -608,7 +613,7 @@ techArticle, originParentTechComment2, originParentTechComment2, new Count(0L), false, false, false, - false ) + false) ); TechCommentsResponse techCommentsResponse6 = response.getContent().get(0); @@ -648,7 +653,8 @@ void getTechCommentsSortByMostCommented() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -940,7 +946,8 @@ void getTechCommentsSortByMostRecommended() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1086,8 +1093,8 @@ void getTechCommentsByCursor() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), - new Count(1L), new Count(12L), new Count(1L), null, company); + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1261,8 +1268,8 @@ void findTechBestComments() { companyRepository.save(company); // 기술 블로그 생성 - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), - new Count(1L), new Count(12L), new Count(1L), null, company); + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); // 댓글 생성 diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechArticleServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechArticleServiceTest.java index bce228d8..41be7215 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechArticleServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechArticleServiceTest.java @@ -11,6 +11,7 @@ import com.dreamypatisiel.devdevdev.domain.entity.*; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; @@ -256,7 +257,8 @@ void getTechArticleNotFoundMemberException() { @DisplayName("회원이 기술블로그 상세를 조회할 때 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundTechArticleException() { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -283,7 +285,8 @@ void getTechArticleNotFoundTechArticleException() { @DisplayName("회원이 기술블로그 상세를 조회할 때 엘라스틱ID가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticIdException() { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -310,7 +313,8 @@ void getTechArticleNotFoundElasticIdException() { @DisplayName("회원이 기술블로그 상세를 조회할 때 엘라스틱 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticTechArticleException() { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), "elasticId", company); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechCommentServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechCommentServiceTest.java index 5cc86d95..3862d28e 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechCommentServiceTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/domain/service/techArticle/MemberTechCommentServiceTest.java @@ -20,6 +20,7 @@ import com.dreamypatisiel.devdevdev.domain.entity.embedded.CommentContents; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; @@ -46,7 +47,6 @@ import com.dreamypatisiel.devdevdev.web.dto.util.CommonResponseUtil; import jakarta.persistence.EntityManager; import java.time.LocalDateTime; -import java.util.Date; import java.util.List; import org.assertj.core.groups.Tuple; import org.junit.jupiter.api.DisplayName; @@ -122,7 +122,8 @@ void registerTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); TechArticle savedTechArticle = techArticleRepository.save(techArticle); Long id = savedTechArticle.getId(); @@ -160,7 +161,8 @@ void registerTechCommentNotFoundTechArticleException() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); TechArticle savedTechArticle = techArticleRepository.save(techArticle); Long id = savedTechArticle.getId() + 1; @@ -221,7 +223,8 @@ void modifyTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -297,7 +300,8 @@ void modifyTechCommentNotFoundTechArticleCommentException() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -330,7 +334,8 @@ void modifyTechCommentAlreadyDeletedException() { userPrincipal.getSocialType().name())); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -370,7 +375,8 @@ void deleteTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -415,7 +421,8 @@ void deleteTechCommentAlreadyDeletedException() { userPrincipal.getSocialType().name())); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -453,7 +460,8 @@ void deleteTechCommentNotFoundException() { userPrincipal.getSocialType().name())); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -487,7 +495,8 @@ void deleteTechCommentAdmin() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -536,7 +545,8 @@ void deleteTechCommentNotByMemberException() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -589,7 +599,8 @@ void registerRepliedTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -647,7 +658,8 @@ void registerRepliedTechCommentToRepliedTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(2L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -710,7 +722,8 @@ void registerRepliedTechCommentNotFoundTechCommentException() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -746,7 +759,8 @@ void registerRepliedTechCommentDeletedTechCommentException() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -799,7 +813,7 @@ void registerRepliedTechCommentNotFoundMemberException() { @Test @DisplayName("회원은 커서 방식으로 기술블로그 댓글/답글을 조회할 수 있다. (등록순)") - void getTechCommentsSortByOLDEST() { + void getTechCommentsSortByOLDEST() { // given SocialMemberDto socialMemberDto = createSocialDto(userId, name, nickname, password, email, socialType, role); Member member = Member.createMemberBy(socialMemberDto); @@ -814,7 +828,8 @@ void getTechCommentsSortByOLDEST() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1109,7 +1124,8 @@ void getTechCommentsSortByLATEST() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1236,7 +1252,7 @@ techArticle, originParentTechComment2, originParentTechComment2, new Count(0L), true, false, false, - false ) + false) ); TechCommentsResponse techCommentsResponse6 = response.getContent().get(0); @@ -1279,7 +1295,8 @@ void getTechCommentsSortByMostCommented() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1574,7 +1591,8 @@ void getTechCommentsSortByMostRecommended() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1723,7 +1741,8 @@ void getTechCommentsByCursor() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1874,7 +1893,8 @@ void recommendTechComment() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(2L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1910,7 +1930,8 @@ void recommendTechCommentCancel() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(2L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1949,7 +1970,8 @@ void recommendTechCommentNotFoundTechCommentException() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -1982,7 +2004,8 @@ void recommendTechCommentDeletedTechCommentException() { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -2071,7 +2094,8 @@ void findTechBestComments() { companyRepository.save(company); // 기술 블로그 생성 - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); @@ -2219,7 +2243,8 @@ void findTechBestCommentsExcludeLessThanOneRecommend() { companyRepository.save(company); // 기술 블로그 생성 - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/BlameControllerTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/BlameControllerTest.java index 4af1d675..4a6c969f 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/BlameControllerTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/BlameControllerTest.java @@ -112,7 +112,7 @@ void blamePick() throws Exception { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 신고 종류 생성 @@ -145,7 +145,7 @@ void blamePickComment() throws Exception { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -296,8 +296,9 @@ private PickComment createPickComment(Pick pick, Member createdBy, String conten return pickComment; } - private Pick createPick(String title, ContentStatus contentStatus, Count commentTotalCount) { + private Pick createPick(Member member, String title, ContentStatus contentStatus, Count commentTotalCount) { return Pick.builder() + .member(member) .title(new Title(title)) .contentStatus(contentStatus) .commentTotalCount(commentTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/MyPageControllerTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/MyPageControllerTest.java index 88575842..9eab99c2 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/MyPageControllerTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/MyPageControllerTest.java @@ -74,6 +74,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; @@ -91,6 +92,8 @@ class MyPageControllerTest extends SupportControllerTest { private static final int TEST_ARTICLES_COUNT = 20; private static List techArticles; + @Autowired + ApplicationContext applicationContext; @Autowired TechArticleRepository techArticleRepository; @Autowired diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/MyPageControllerUsedMockServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/MyPageControllerUsedMockServiceTest.java new file mode 100644 index 00000000..71704320 --- /dev/null +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/MyPageControllerUsedMockServiceTest.java @@ -0,0 +1,226 @@ +package com.dreamypatisiel.devdevdev.web.controller; + +import static com.dreamypatisiel.devdevdev.web.dto.response.ResultType.SUCCESS; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.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; + +import com.dreamypatisiel.devdevdev.domain.entity.Member; +import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType; +import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; +import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; +import com.dreamypatisiel.devdevdev.domain.repository.member.MemberRepository; +import com.dreamypatisiel.devdevdev.domain.service.member.MemberService; +import com.dreamypatisiel.devdevdev.global.constant.SecurityConstant; +import com.dreamypatisiel.devdevdev.global.security.oauth2.model.SocialMemberDto; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.response.ResultType; +import com.dreamypatisiel.devdevdev.web.dto.response.comment.MyWrittenCommentResponse; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.List; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; + +public class MyPageControllerUsedMockServiceTest extends SupportControllerTest { + + @Autowired + MemberRepository memberRepository; + @MockBean + MemberService memberService; + + @Test + @DisplayName("회원이 내가 썼어요 댓글을 조회한다.") + void getMyWrittenComments() throws Exception { + // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + Pageable pageable = PageRequest.of(0, 6); + LocalDateTime now = LocalDateTime.of(2025, 1, 1, 0, 0, 0); + + // 응답 생성 + MyWrittenCommentResponse pickWrittenComment = createMyWrittenCommentResponse( + "PICK_1_1", 1L, "픽픽픽 제목", 1L, "PICK", "픽픽픽 댓글입니다.", 111L, now, "픽픽픽 A", + PickOptionType.firstPickOption.name()); + MyWrittenCommentResponse techWrittenComment = createMyWrittenCommentResponse( + "TECH_1_1", 1L, "기술블로그 제목", 1L, "TECH", "기술블로그 댓글입니다.", 54321L, now, null, null); + List myWrittenComments = List.of(pickWrittenComment, techWrittenComment); + SliceCustom result = new SliceCustom<>(myWrittenComments, pageable, false, 2L); + + // when + when(memberService.findMyWrittenComments(eq(pageable), any(), any())).thenReturn(result); + + // then + mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .queryParam("pickCommentId", "1000") + .queryParam("techCommentId", "1000") + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .header(SecurityConstant.AUTHORIZATION_HEADER, SecurityConstant.BEARER_PREFIX + accessToken)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.resultType").value(SUCCESS.name())) + .andExpect(jsonPath("$.data").isNotEmpty()) + .andExpect(jsonPath("$.data.content").isArray()) + .andExpect(jsonPath("$.data.content.[0].uniqueCommentId").isString()) + .andExpect(jsonPath("$.data.content.[0].postId").isNumber()) + .andExpect(jsonPath("$.data.content.[0].postTitle").isString()) + .andExpect(jsonPath("$.data.content.[0].commentId").isNumber()) + .andExpect(jsonPath("$.data.content.[0].commentType").isString()) + .andExpect(jsonPath("$.data.content.[0].commentContents").isString()) + .andExpect(jsonPath("$.data.content.[0].commentRecommendTotalCount").isNumber()) + .andExpect(jsonPath("$.data.content.[0].commentCreatedAt").isString()) + .andExpect(jsonPath("$.data.content.[0].pickOptionTitle").isString()) + .andExpect(jsonPath("$.data.content.[0].pickOptionType").isString()) + .andExpect(jsonPath("$.data.content.[1].uniqueCommentId").isString()) + .andExpect(jsonPath("$.data.content.[1].postId").isNumber()) + .andExpect(jsonPath("$.data.content.[1].postTitle").isString()) + .andExpect(jsonPath("$.data.content.[1].commentId").isNumber()) + .andExpect(jsonPath("$.data.content.[1].commentType").isString()) + .andExpect(jsonPath("$.data.content.[1].commentContents").isString()) + .andExpect(jsonPath("$.data.content.[1].commentCreatedAt").isString()) + .andExpect(jsonPath("$.data.content.[1].pickOptionTitle").isEmpty()) + .andExpect(jsonPath("$.data.content.[1].pickOptionType").isEmpty()) + .andExpect(jsonPath("$.data.pageable.pageNumber").isNumber()) + .andExpect(jsonPath("$.data.pageable.pageSize").isNumber()) + .andExpect(jsonPath("$.data.pageable.sort").isNotEmpty()) + .andExpect(jsonPath("$.data.pageable.sort.empty").isBoolean()) + .andExpect(jsonPath("$.data.pageable.sort.sorted").isBoolean()) + .andExpect(jsonPath("$.data.pageable.sort.unsorted").isBoolean()) + .andExpect(jsonPath("$.data.pageable.offset").isNumber()) + .andExpect(jsonPath("$.data.pageable.paged").isBoolean()) + .andExpect(jsonPath("$.data.pageable.unpaged").isBoolean()) + .andExpect(jsonPath("$.data.totalElements").value(2)) + .andExpect(jsonPath("$.data.first").isBoolean()) + .andExpect(jsonPath("$.data.last").isBoolean()) + .andExpect(jsonPath("$.data.size").isNumber()) + .andExpect(jsonPath("$.data.number").isNumber()) + .andExpect(jsonPath("$.data.sort").isNotEmpty()) + .andExpect(jsonPath("$.data.sort.empty").isBoolean()) + .andExpect(jsonPath("$.data.sort.sorted").isBoolean()) + .andExpect(jsonPath("$.data.sort.unsorted").isBoolean()) + .andExpect(jsonPath("$.data.numberOfElements").isNumber()) + .andExpect(jsonPath("$.data.empty").isBoolean()); + } + + @Test + @DisplayName("회원이 작성한 댓글을 조회할 때 회원이 유효하지 않으면 예외가 발생한다.") + void getMyWrittenCommentsMemberException() throws Exception { + // given + Pageable pageable = PageRequest.of(0, 6); + + // when // then + ResultActions actions = mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(print()) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("$.resultType").value(ResultType.FAIL.name())) + .andExpect(jsonPath("$.message").isString()) + .andExpect(jsonPath("$.errorCode").value(HttpStatus.UNAUTHORIZED.value())); + } + + @Disabled + @Test + @DisplayName("회원이 작성한 댓글을 조회할 때 기술블로그 댓글 아이디가 없으면 예외가 발생한다.") + void getMyWrittenCommentsTechCommentIdBindException() throws Exception { + // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + Pageable pageable = PageRequest.of(0, 6); + + // when // then + mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .header(SecurityConstant.AUTHORIZATION_HEADER, SecurityConstant.BEARER_PREFIX + accessToken)) + .andDo(print()) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.resultType").value(ResultType.FAIL.name())) + .andExpect(jsonPath("$.message").isString()) + .andExpect(jsonPath("$.errorCode").value(HttpStatus.BAD_REQUEST.value())); + } + + @Disabled + @Test + @DisplayName("회원이 작성한 댓글을 조회할 때 픽픽픽 댓글 아이디가 없으면 예외가 발생한다.") + void getMyWrittenCommentsPickCommentIdBindException() throws Exception { + // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + Pageable pageable = PageRequest.of(0, 6); + + // when // then + mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .queryParam("techCommentId", "1000") + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .header(SecurityConstant.AUTHORIZATION_HEADER, SecurityConstant.BEARER_PREFIX + accessToken)) + .andDo(print()) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.resultType").value(ResultType.FAIL.name())) + .andExpect(jsonPath("$.message").isString()) + .andExpect(jsonPath("$.errorCode").value(HttpStatus.BAD_REQUEST.value())); + } + + private static MyWrittenCommentResponse createMyWrittenCommentResponse(String uniqueCommentId, Long postId, + String postTitle, + Long commentId, + String commentType, + String commentContents, + Long commentRecommendTotalCount, + LocalDateTime commentCreatedAt, + String pickOptionTitle, + String pickOptionType) { + return MyWrittenCommentResponse.builder() + .uniqueCommentId(uniqueCommentId) + .postId(postId) + .postTitle(postTitle) + .commentId(commentId) + .commentType(commentType) + .commentContents(commentContents) + .commentRecommendTotalCount(commentRecommendTotalCount) + .commentCreatedAt(commentCreatedAt) + .pickOptionTitle(pickOptionTitle) + .pickOptionType(pickOptionType) + .build(); + } + + private SocialMemberDto createSocialDto(String userId, String name, String nickName, String password, String email, + String socialType, String role) { + return SocialMemberDto.builder() + .userId(userId) + .name(name) + .nickname(nickName) + .password(password) + .email(email) + .socialType(SocialType.valueOf(socialType)) + .role(Role.valueOf(role)) + .build(); + } +} diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/pick/PickControllerTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/pick/PickControllerTest.java index 3b48b5ce..5e90aff1 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/pick/PickControllerTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/pick/PickControllerTest.java @@ -105,24 +105,27 @@ class PickControllerTest extends SupportControllerTest { @DisplayName("회원이 픽픽픽 메인을 조회한다.") void getPicksMainByMember() throws Exception { // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + PickOption pickOption1 = createPickOption(new Title("픽옵션1"), new PickOptionContents("픽콘텐츠1"), new Count(1), firstPickOption); PickOption pickOption2 = createPickOption(new Title("픽옵션2"), new PickOptionContents("픽콘텐츠2"), new Count(1), secondPickOption); + Title title = new Title("픽1타이틀"); Count count = new Count(2); String thumbnailUrl = "https://devdevdev.co.kr/devdevdev/api/v1/pick/image/1"; String author = "운영자"; - Pick pick = createPick(title, count, count, count, - thumbnailUrl, author, ContentStatus.APPROVAL, List.of(pickOption1, pickOption2), List.of()); + Pick pick = createPick(member, title, count, count, count, thumbnailUrl, author, ContentStatus.APPROVAL, + List.of(pickOption1, pickOption2), List.of()); pick.changePopularScore(pickPopularScorePolicy); pickRepository.save(pick); pickOptionRepository.saveAll(List.of(pickOption1, pickOption2)); - SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", - "꿈빛파티시엘", "1234", email, socialType, role); - Member member = Member.createMemberBy(socialMemberDto); member.updateRefreshToken(refreshToken); memberRepository.save(member); @@ -183,15 +186,21 @@ void getPicksMainByMember() throws Exception { @DisplayName("익명 사용자가 픽픽픽 메인을 조회한다.") void getPicksMainByAnonymous() throws Exception { // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + PickOption pickOption1 = createPickOption(new Title("픽옵션1"), new PickOptionContents("픽콘텐츠1"), new Count(1), firstPickOption); PickOption pickOption2 = createPickOption(new Title("픽옵션2"), new PickOptionContents("픽콘텐츠2"), new Count(1), secondPickOption); + Title title = new Title("픽1타이틀"); Count count = new Count(2); String thumbnailUrl = "https://devdevdev.co.kr/devdevdev/api/v1/pick/image/1"; String author = "운영자"; - Pick pick = createPick(title, count, count, count, + Pick pick = createPick(member, title, count, count, count, thumbnailUrl, author, ContentStatus.APPROVAL, List.of(pickOption1, pickOption2), List.of()); pick.changePopularScore(pickPopularScorePolicy); @@ -1389,13 +1398,14 @@ private SocialMemberDto createSocialDto(String userId, String name, String nickN .build(); } - private Pick createPick(Title title, Count pickVoteTotalCount, Count pickViewTotalCount, + private Pick createPick(Member member, Title title, Count pickVoteTotalCount, Count pickViewTotalCount, Count pickcommentTotalCount, String thumbnailUrl, String author, ContentStatus contentStatus, List pickOptions, List pickVotes ) { Pick pick = Pick.builder() + .member(member) .title(title) .voteTotalCount(pickVoteTotalCount) .viewTotalCount(pickViewTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleCommentControllerTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleCommentControllerTest.java index 880f39b7..8f6d3feb 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleCommentControllerTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleCommentControllerTest.java @@ -19,6 +19,7 @@ import com.dreamypatisiel.devdevdev.domain.entity.embedded.CommentContents; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; @@ -78,7 +79,8 @@ void registerTechCommentByAnonymous() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -106,7 +108,8 @@ void registerTechComment() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -142,7 +145,8 @@ void registerTechCommentNotFoundTechArticleException() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -177,7 +181,8 @@ void registerTechCommentNotFoundMemberException() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -207,7 +212,8 @@ void registerTechCommentContentsIsNullException(String contents) throws Exceptio Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -242,7 +248,8 @@ void modifyTechComment() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -282,7 +289,8 @@ void modifyTechCommentContentsIsNullException(String contents) throws Exception member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -320,7 +328,8 @@ void modifyTechCommentNotFoundException() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -353,7 +362,8 @@ void modifyTechCommentAlreadyDeletedException() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -394,7 +404,8 @@ void deleteTechComment() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -430,7 +441,8 @@ void deleteTechCommentNotFoundException() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -457,7 +469,8 @@ void registerRepliedTechComment() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -510,7 +523,8 @@ void registerRepliedTechCommentContentsIsNullException(String contents) throws E Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); TechArticle savedTechArticle = techArticleRepository.save(techArticle); Long techArticleId = savedTechArticle.getId(); @@ -558,7 +572,8 @@ void getTechComments() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -674,7 +689,8 @@ void recommendTechComment() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); @@ -722,7 +738,8 @@ void getTechBestComments() throws Exception { companyRepository.save(company); // 기술 블로그 생성 - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); @@ -808,7 +825,8 @@ void getTechBestCommentsAnonymous() throws Exception { companyRepository.save(company); // 기술 블로그 생성 - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleControllerTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleControllerTest.java index 2f9651e7..39ac8493 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleControllerTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/controller/techArticle/TechArticleControllerTest.java @@ -18,12 +18,13 @@ import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; -import com.dreamypatisiel.devdevdev.domain.repository.techArticle.BookmarkRepository; import com.dreamypatisiel.devdevdev.domain.repository.CompanyRepository; import com.dreamypatisiel.devdevdev.domain.repository.member.MemberRepository; +import com.dreamypatisiel.devdevdev.domain.repository.techArticle.BookmarkRepository; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechArticleRepository; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechArticleSort; import com.dreamypatisiel.devdevdev.elastic.domain.document.ElasticTechArticle; @@ -413,7 +414,8 @@ void getTechArticleNotFoundMemberException() throws Exception { @DisplayName("기술블로그 상세를 조회할 때 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundTechArticleException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -435,7 +437,8 @@ void getTechArticleNotFoundTechArticleException() throws Exception { @DisplayName("기술블로그 상세를 조회할 때 엘라스틱ID가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticIdException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); TechArticle savedTechArticle = techArticleRepository.save(techArticle); @@ -456,7 +459,8 @@ void getTechArticleNotFoundElasticIdException() throws Exception { @DisplayName("기술블로그 상세를 조회할 때 엘라스틱 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticTechArticleException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), "elasticId", company); @@ -503,7 +507,8 @@ void updateBookmark() throws Exception { @DisplayName("회원이 기술블로그 북마크를 요청할 때 존재하지 않는 기술블로그라면 예외가 발생한다.") void updateBookmarkNotFoundTechArticleException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -575,7 +580,8 @@ void updateRecommend() throws Exception { @DisplayName("회원이 기술블로그 추천을 요청할 때 존재하지 않는 기술블로그라면 예외가 발생한다.") void updateRecommendNotFoundTechArticleException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/BlameControllerDocsTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/BlameControllerDocsTest.java index 723d9a09..b5933da9 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/BlameControllerDocsTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/BlameControllerDocsTest.java @@ -150,7 +150,7 @@ void blamePick() throws Exception { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 신고 종류 생성 @@ -211,7 +211,7 @@ void blamePickComment() throws Exception { memberRepository.save(member); // 픽픽픽 생성 - Pick pick = createPick("픽픽픽", ContentStatus.APPROVAL, new Count(0L)); + Pick pick = createPick(member, "픽픽픽", ContentStatus.APPROVAL, new Count(0L)); pickRepository.save(pick); // 픽픽픽 댓글 생성 @@ -447,8 +447,9 @@ private PickComment createPickComment(Pick pick, Member createdBy, String conten return pickComment; } - private Pick createPick(String title, ContentStatus contentStatus, Count commentTotalCount) { + private Pick createPick(Member member, String title, ContentStatus contentStatus, Count commentTotalCount) { return Pick.builder() + .member(member) .title(new Title(title)) .contentStatus(contentStatus) .commentTotalCount(commentTotalCount) diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/MyPageControllerDocsUsedMockServiceTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/MyPageControllerDocsUsedMockServiceTest.java new file mode 100644 index 00000000..381ab133 --- /dev/null +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/MyPageControllerDocsUsedMockServiceTest.java @@ -0,0 +1,316 @@ +package com.dreamypatisiel.devdevdev.web.docs; + +import static com.dreamypatisiel.devdevdev.global.constant.SecurityConstant.AUTHORIZATION_HEADER; +import static com.dreamypatisiel.devdevdev.web.docs.format.ApiDocsFormatGenerator.authenticationType; +import static com.dreamypatisiel.devdevdev.web.docs.format.ApiDocsFormatGenerator.commentIdType; +import static com.dreamypatisiel.devdevdev.web.docs.format.ApiDocsFormatGenerator.myWrittenCommentSort; +import static com.dreamypatisiel.devdevdev.web.docs.format.ApiDocsFormatGenerator.stringOrNull; +import static com.dreamypatisiel.devdevdev.web.docs.format.ApiDocsFormatGenerator.uniqueCommentIdType; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.dreamypatisiel.devdevdev.domain.entity.Member; +import com.dreamypatisiel.devdevdev.domain.entity.enums.PickOptionType; +import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; +import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; +import com.dreamypatisiel.devdevdev.domain.repository.member.MemberRepository; +import com.dreamypatisiel.devdevdev.domain.service.member.MemberService; +import com.dreamypatisiel.devdevdev.global.constant.SecurityConstant; +import com.dreamypatisiel.devdevdev.global.security.oauth2.model.SocialMemberDto; +import com.dreamypatisiel.devdevdev.web.dto.SliceCustom; +import com.dreamypatisiel.devdevdev.web.dto.response.comment.MyWrittenCommentResponse; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.List; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.ResultActions; + +public class MyPageControllerDocsUsedMockServiceTest extends SupportControllerDocsTest { + + @Autowired + MemberRepository memberRepository; + @MockBean + MemberService memberService; + + @Test + @DisplayName("회원이 내가 썼어요 댓글을 조회한다.") + void getMyWrittenComments() throws Exception { + // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + Pageable pageable = PageRequest.of(0, 6); + LocalDateTime now = LocalDateTime.of(2025, 1, 1, 0, 0, 0); + + // 응답 생성 + MyWrittenCommentResponse pickWrittenComment = createMyWrittenCommentResponse( + "PICK_1_1", 1L, "픽픽픽 제목", 1L, "PICK", "픽픽픽 댓글입니다.", 111L, now, "픽픽픽 A", + PickOptionType.firstPickOption.name()); + MyWrittenCommentResponse techWrittenComment = createMyWrittenCommentResponse( + "TECH_1_1", 1L, "기술블로그 제목", 1L, "TECH", "기술블로그 댓글입니다.", 54321L, now, null, null); + List myWrittenComments = List.of(pickWrittenComment, techWrittenComment); + SliceCustom result = new SliceCustom<>(myWrittenComments, pageable, false, 2L); + + // when + when(memberService.findMyWrittenComments(eq(pageable), any(), any())).thenReturn(result); + + // then + ResultActions actions = mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .queryParam("pickCommentId", "1000") + .queryParam("techCommentId", "1000") + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .header(SecurityConstant.AUTHORIZATION_HEADER, SecurityConstant.BEARER_PREFIX + accessToken)) + .andDo(print()) + .andExpect(status().isOk()); + + // docs + actions.andDo(document("mypage-comments", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestHeaders( + headerWithName(AUTHORIZATION_HEADER).description("Bearer 엑세스 토큰") + ), + queryParameters( + parameterWithName("size").optional().description("조회되는 데이터 수"), + parameterWithName("pickCommentId").optional().description("가장 작은 픽픽픽 아이디"), + parameterWithName("techCommentId").optional().description("가장 작은 기술블로그 아이디"), + parameterWithName("commentFilter").optional().description("댓글 정렬 기준") + .attributes(myWrittenCommentSort()) + ), + responseFields( + fieldWithPath("resultType").type(JsonFieldType.STRING).description("응답 결과"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("응답 데이터"), + + fieldWithPath("data.content").type(JsonFieldType.ARRAY).description("기술블로그 메인 배열"), + fieldWithPath("data.content.[].uniqueCommentId").type(JsonFieldType.STRING) + .description("댓글 유니크 아이디").attributes(uniqueCommentIdType(), authenticationType()), + fieldWithPath("data.content.[].postId").type(JsonFieldType.NUMBER) + .description("픽픽픽 | 기술블로그 아이디").attributes(authenticationType()), + fieldWithPath("data.content.[].postTitle").type(JsonFieldType.STRING) + .description("픽픽픽 | 기술블로그 제목").attributes(authenticationType()), + fieldWithPath("data.content.[].commentId").type(JsonFieldType.NUMBER) + .description("픽픽픽 | 기술블로그 댓글 아이디").attributes(authenticationType()), + fieldWithPath("data.content.[].commentType").type(JsonFieldType.STRING) + .description("픽픽픽 | 기술블로그 댓글 타입").attributes(commentIdType(), authenticationType()), + fieldWithPath("data.content.[].commentContents").type(JsonFieldType.STRING) + .description("픽픽픽 | 기술블로그 댓글 내용").attributes(authenticationType()), + fieldWithPath("data.content.[].commentRecommendTotalCount").type(JsonFieldType.NUMBER) + .description("픽픽픽 | 기술블로그 댓글 추천 갯수").attributes(authenticationType()), + fieldWithPath("data.content.[].commentCreatedAt").type(JsonFieldType.STRING) + .description("픽픽픽 | 기술블로그 댓글 생성일").attributes(authenticationType()), + fieldWithPath("data.content.[].pickOptionTitle").optional().type(JsonFieldType.STRING) + .description("픽픽픽 옵션 제목").attributes(stringOrNull(), authenticationType()), + fieldWithPath("data.content.[].pickOptionType").optional().type(JsonFieldType.STRING) + .description("픽픽픽 옵션 타입").attributes(stringOrNull(), authenticationType()), + + fieldWithPath("data.pageable").type(JsonFieldType.OBJECT).description("페이지네이션 정보") + .attributes(authenticationType()), + fieldWithPath("data.pageable.pageNumber").type(JsonFieldType.NUMBER).description("페이지 번호") + .attributes(authenticationType()), + fieldWithPath("data.pageable.pageSize").type(JsonFieldType.NUMBER).description("페이지 사이즈") + .attributes(authenticationType()), + + fieldWithPath("data.pageable.sort").type(JsonFieldType.OBJECT).description("정렬 정보") + .attributes(authenticationType()), + fieldWithPath("data.pageable.sort.empty").type(JsonFieldType.BOOLEAN) + .description("정렬 정보가 비어있는지 여부").attributes(authenticationType()), + fieldWithPath("data.pageable.sort.sorted").type(JsonFieldType.BOOLEAN).description("정렬 여부") + .attributes(authenticationType()), + fieldWithPath("data.pageable.sort.unsorted").type(JsonFieldType.BOOLEAN).description("비정렬 여부") + .attributes(authenticationType()), + + fieldWithPath("data.pageable.offset").type(JsonFieldType.NUMBER) + .description("페이지 오프셋 (페이지 크기 * 페이지 번호)").attributes(authenticationType()), + fieldWithPath("data.pageable.paged").type(JsonFieldType.BOOLEAN).description("페이지 정보 포함 여부") + .attributes(authenticationType()), + fieldWithPath("data.pageable.unpaged").type(JsonFieldType.BOOLEAN).description("페이지 정보 비포함 여부") + .attributes(authenticationType()), + + fieldWithPath("data.totalElements").type(JsonFieldType.NUMBER).description("데이터 전체 갯수") + .attributes(authenticationType()), + fieldWithPath("data.first").type(JsonFieldType.BOOLEAN).description("현재 페이지가 첫 페이지 여부") + .attributes(authenticationType()), + fieldWithPath("data.last").type(JsonFieldType.BOOLEAN).description("현재 페이지가 마지막 페이지 여부") + .attributes(authenticationType()), + fieldWithPath("data.size").type(JsonFieldType.NUMBER).description("페이지 크기") + .attributes(authenticationType()), + fieldWithPath("data.number").type(JsonFieldType.NUMBER).description("현재 페이지") + .attributes(authenticationType()), + + fieldWithPath("data.sort").type(JsonFieldType.OBJECT).description("정렬 정보") + .attributes(authenticationType()), + fieldWithPath("data.sort.empty").type(JsonFieldType.BOOLEAN).description("정렬 정보가 비어있는지 여부") + .attributes(authenticationType()), + fieldWithPath("data.sort.sorted").type(JsonFieldType.BOOLEAN).description("정렬 상태 여부") + .attributes(authenticationType()), + fieldWithPath("data.sort.unsorted").type(JsonFieldType.BOOLEAN).description("비정렬 상태 여부") + .attributes(authenticationType()), + fieldWithPath("data.numberOfElements").type(JsonFieldType.NUMBER).description("현재 페이지 데이터 수") + .attributes(authenticationType()), + fieldWithPath("data.empty").type(JsonFieldType.BOOLEAN).description("현재 빈 페이지 여부") + .attributes(authenticationType()) + ) + )); + } + + @Test + @DisplayName("회원이 작성한 댓글을 조회할 때 회원이 유효하지 않으면 예외가 발생한다.") + void getMyWrittenCommentsMemberException() throws Exception { + // given + Pageable pageable = PageRequest.of(0, 6); + + // when // then + ResultActions actions = mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(print()) + .andExpect(status().isUnauthorized()); + + // docs + actions.andDo(document("mypage-comments-member-exception", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + responseFields( + fieldWithPath("resultType").type(JsonFieldType.STRING).description("응답 결과"), + fieldWithPath("message").type(JsonFieldType.STRING).description("에러 메시지"), + fieldWithPath("errorCode").type(JsonFieldType.NUMBER).description("에러 코드") + ) + )); + } + + @Disabled + @Test + @DisplayName("회원이 작성한 댓글을 조회할 때 기술블로그 댓글 아이디가 없으면 예외가 발생한다.") + void getMyWrittenCommentsTechCommentIdBindException() throws Exception { + // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + Pageable pageable = PageRequest.of(0, 6); + + // when // then + ResultActions actions = mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .header(AUTHORIZATION_HEADER, SecurityConstant.BEARER_PREFIX + accessToken)) + .andDo(print()) + .andExpect(status().isBadRequest()); + + // docs + actions.andDo(document("mypage-comments-tech-comment-id-bind-exception", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestHeaders( + headerWithName(AUTHORIZATION_HEADER).description("Bearer 엑세스 토큰") + ), + responseFields( + fieldWithPath("resultType").type(JsonFieldType.STRING).description("응답 결과"), + fieldWithPath("message").type(JsonFieldType.STRING).description("에러 메시지"), + fieldWithPath("errorCode").type(JsonFieldType.NUMBER).description("에러 코드") + ) + )); + } + + @Disabled + @Test + @DisplayName("회원이 작성한 댓글을 조회할 때 픽픽픽 댓글 아이디가 없으면 예외가 발생한다.") + void getMyWrittenCommentsPickCommentIdBindException() throws Exception { + // given + SocialMemberDto socialMemberDto = createSocialDto("dreamy5patisiel", "꿈빛파티시엘", + "꿈빛파티시엘", "1234", email, socialType, role); + Member member = Member.createMemberBy(socialMemberDto); + memberRepository.save(member); + + Pageable pageable = PageRequest.of(0, 6); + + // when // then + ResultActions actions = mockMvc.perform(get("/devdevdev/api/v1/mypage/comments") + .queryParam("size", String.valueOf(pageable.getPageSize())) + .queryParam("techCommentId", "1000") + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .header(AUTHORIZATION_HEADER, SecurityConstant.BEARER_PREFIX + accessToken)) + .andDo(print()) + .andExpect(status().isBadRequest()); + + // docs + actions.andDo(document("mypage-comments-pick-comment-id-bind-exception", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestHeaders( + headerWithName(AUTHORIZATION_HEADER).description("Bearer 엑세스 토큰") + ), + responseFields( + fieldWithPath("resultType").type(JsonFieldType.STRING).description("응답 결과"), + fieldWithPath("message").type(JsonFieldType.STRING).description("에러 메시지"), + fieldWithPath("errorCode").type(JsonFieldType.NUMBER).description("에러 코드") + ) + )); + } + + private static MyWrittenCommentResponse createMyWrittenCommentResponse(String uniqueCommentId, Long postId, + String postTitle, + Long commentId, + String commentType, + String commentContents, + Long commentRecommendTotalCount, + LocalDateTime commentCreatedAt, + String pickOptionTitle, + String pickOptionType) { + return MyWrittenCommentResponse.builder() + .uniqueCommentId(uniqueCommentId) + .postId(postId) + .postTitle(postTitle) + .commentId(commentId) + .commentType(commentType) + .commentContents(commentContents) + .commentRecommendTotalCount(commentRecommendTotalCount) + .commentCreatedAt(commentCreatedAt) + .pickOptionTitle(pickOptionTitle) + .pickOptionType(pickOptionType) + .build(); + } + + private SocialMemberDto createSocialDto(String userId, String name, String nickName, String password, String email, + String socialType, String role) { + return SocialMemberDto.builder() + .userId(userId) + .name(name) + .nickname(nickName) + .password(password) + .email(email) + .socialType(SocialType.valueOf(socialType)) + .role(Role.valueOf(role)) + .build(); + } +} diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleCommentControllerDocsTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleCommentControllerDocsTest.java index 6018bab3..2bd0ea02 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleCommentControllerDocsTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleCommentControllerDocsTest.java @@ -38,6 +38,7 @@ import com.dreamypatisiel.devdevdev.domain.entity.embedded.CommentContents; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; @@ -100,7 +101,8 @@ void registerTechCommentByAnonymous() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long id = techArticle.getId(); @@ -141,7 +143,8 @@ void registerTechComment() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -198,7 +201,8 @@ void registerTechCommentNotFoundTechArticleException() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -248,7 +252,8 @@ void registerTechCommentNotFoundMemberException() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -294,8 +299,8 @@ void registerTechCommentContentsIsNullException(String contents) throws Exceptio Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), - new Count(1L), new Count(1L), new Count(1L), null, company); + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); TechArticle savedTechArticle = techArticleRepository.save(techArticle); Long techArticleId = savedTechArticle.getId(); @@ -342,7 +347,8 @@ void modifyTechComment() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -404,7 +410,8 @@ void modifyTechCommentContentsIsNullException(String contents) throws Exception member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -458,7 +465,8 @@ void modifyTechCommentNotFoundException() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -507,7 +515,8 @@ void deleteTechComment() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -562,7 +571,8 @@ void deleteTechCommentNotFoundException() throws Exception { member.updateRefreshToken(refreshToken); memberRepository.save(member); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -605,7 +615,8 @@ void registerTechReply() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -680,7 +691,8 @@ void registerTechReplyContentsIsNullException(String contents) throws Exception Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); TechArticle savedTechArticle = techArticleRepository.save(techArticle); Long techArticleId = savedTechArticle.getId(); @@ -744,7 +756,8 @@ void getTechComments() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); Long techArticleId = techArticle.getId(); @@ -970,7 +983,8 @@ void recommendTechComment() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); @@ -1026,7 +1040,8 @@ void recommendTechCommentNotFoundTechComment() throws Exception { Company company = createCompany("꿈빛 파티시엘", "https://example.png", "https://example.com", "https://example.com"); companyRepository.save(company); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); techArticleRepository.save(techArticle); @@ -1084,7 +1099,8 @@ void getTechBestComments() throws Exception { companyRepository.save(company); // 기술 블로그 생성 - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(12L), new Count(1L), null, company); techArticleRepository.save(techArticle); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleControllerDocsTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleControllerDocsTest.java index 73eb48f6..b91a4fdb 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleControllerDocsTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/TechArticleControllerDocsTest.java @@ -28,6 +28,7 @@ import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.domain.entity.enums.Role; import com.dreamypatisiel.devdevdev.domain.entity.enums.SocialType; @@ -427,7 +428,8 @@ void getTechArticleNotFoundMemberException() throws Exception { @DisplayName("기술블로그 상세를 조회할 때 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundTechArticleException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -462,7 +464,8 @@ void getTechArticleNotFoundTechArticleException() throws Exception { @DisplayName("기술블로그 상세를 조회할 때 엘라스틱ID가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticIdException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); @@ -491,7 +494,8 @@ void getTechArticleNotFoundElasticIdException() throws Exception { @DisplayName("기술블로그 상세를 조회할 때 엘라스틱 기술블로그가 존재하지 않으면 예외가 발생한다.") void getTechArticleNotFoundElasticTechArticleException() throws Exception { // given - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), "elasticId", company); diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/format/ApiDocsFormatGenerator.java b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/format/ApiDocsFormatGenerator.java index 73234195..d5563235 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/docs/format/ApiDocsFormatGenerator.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/docs/format/ApiDocsFormatGenerator.java @@ -10,6 +10,7 @@ import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechArticleSort; import com.dreamypatisiel.devdevdev.domain.repository.techArticle.TechCommentSort; import com.dreamypatisiel.devdevdev.domain.service.pick.MemberPickService; +import com.dreamypatisiel.devdevdev.web.dto.request.comment.MyWrittenCommentFilter; import com.dreamypatisiel.devdevdev.web.dto.request.common.BlamePathType; import java.util.Arrays; import java.util.stream.Collectors; @@ -104,4 +105,20 @@ static Attributes.Attribute blamePathType() { return key(FORMAT).value(blamePathType); } + + static Attributes.Attribute uniqueCommentIdType() { + return key(FORMAT).value("${commentType}_${postId}_${commentId}"); + } + + static Attributes.Attribute commentIdType() { + return key(FORMAT).value("PICK | TECH"); + } + + static Attributes.Attribute myWrittenCommentSort() { + String blamePathType = Arrays.stream(MyWrittenCommentFilter.values()) + .map(Enum::name) + .collect(Collectors.joining(COMMA)); + + return key(FORMAT).value(blamePathType); + } } diff --git a/src/test/java/com/dreamypatisiel/devdevdev/web/dto/response/techArticle/TechArticleMainResponseTest.java b/src/test/java/com/dreamypatisiel/devdevdev/web/dto/response/techArticle/TechArticleMainResponseTest.java index f4b2cd19..4652fd79 100644 --- a/src/test/java/com/dreamypatisiel/devdevdev/web/dto/response/techArticle/TechArticleMainResponseTest.java +++ b/src/test/java/com/dreamypatisiel/devdevdev/web/dto/response/techArticle/TechArticleMainResponseTest.java @@ -1,18 +1,20 @@ package com.dreamypatisiel.devdevdev.web.dto.response.techArticle; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import com.dreamypatisiel.devdevdev.domain.entity.Company; import com.dreamypatisiel.devdevdev.domain.entity.TechArticle; import com.dreamypatisiel.devdevdev.domain.entity.embedded.CompanyName; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Count; +import com.dreamypatisiel.devdevdev.domain.entity.embedded.Title; import com.dreamypatisiel.devdevdev.domain.entity.embedded.Url; import com.dreamypatisiel.devdevdev.elastic.domain.document.ElasticTechArticle; +import java.time.LocalDate; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.time.LocalDate; - -import static org.junit.jupiter.api.Assertions.*; - class TechArticleMainResponseTest { @Test @@ -22,7 +24,8 @@ public void setThumbnailImageWhenPresent() { Company company = createCompany("꿈빛 파티시엘", "https://officialImageUrl.png", "https://officialUrl.com", "https://careerUrl.com"); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); ElasticTechArticle elasticTechArticle = createElasticTechArticle("elasticId", "타이틀", LocalDate.now(), @@ -47,7 +50,8 @@ public void setLogoImageWhenThumbnailIsAbsent() { Company company = createCompany("꿈빛 파티시엘", "https://officialImageUrl.png", "https://officialUrl.com", "https://careerUrl.com"); - TechArticle techArticle = TechArticle.createTechArticle(new Url("https://example.com"), new Count(1L), + TechArticle techArticle = TechArticle.createTechArticle(new Title("기술블로그 제목"), new Url("https://example.com"), + new Count(1L), new Count(1L), new Count(1L), new Count(1L), null, company); ElasticTechArticle elasticTechArticle = createElasticTechArticle("elasticId", "타이틀", LocalDate.now(), diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index c0e64474..812b9456 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -46,8 +46,16 @@ spring: max-idle: 8 min-idle: 2 +#MyBatis +mybatis: + type-aliases-package: com.dreamypatisiel.devdevdev.domain.repository + configuration: + map-underscore-to-camel-case: true + mapper-locations: classpath:mapper/**/*.xml + logging: level: org.hibernate.SQL: DEBUG org.hibernate.type: TRACE - org.springframework.jdbc: DEBUG \ No newline at end of file + org.springframework.jdbc: DEBUG + com.dreamypatisiel.devdevdev: TRACE \ No newline at end of file