diff --git a/backend/src/acceptanceTest/java/wooteco/prolog/steps/ArticleStepDefinitions.java b/backend/src/acceptanceTest/java/wooteco/prolog/steps/ArticleStepDefinitions.java index cbbb977c7..4b53ca4c3 100644 --- a/backend/src/acceptanceTest/java/wooteco/prolog/steps/ArticleStepDefinitions.java +++ b/backend/src/acceptanceTest/java/wooteco/prolog/steps/ArticleStepDefinitions.java @@ -115,6 +115,25 @@ public class ArticleStepDefinitions extends AcceptanceSteps { assertAll( () -> assertThat(statusCode).isEqualTo(HttpStatus.OK.value()) ); - //아티클 단건 조회 변경 시, 단건 조회로 bookmark 여부까지 검증해보기 + //아티클 단건 조회에 북마크 여부가 추가되면 단건 조회로 bookmark 여부까지 검증해보기 + } + + @When("{long}번 아티클에 좋아요 요청을 보내면") + public void 아티클에_좋아요_요청을_보내면(final Long articleId) { + //final String articleUrl = context.response.header("Location"); + final ArticleBookmarkRequest request = new ArticleBookmarkRequest(true); + context.invokeHttpPutWithToken( + String.format("/articles/%d/likes", articleId), + request + ); + } + + @Then("아티클에 좋아요가 등록된다") + public void 아티클에_좋아요가_등록된다() { + final int statusCode = context.response.statusCode(); + assertAll( + () -> assertThat(statusCode).isEqualTo(HttpStatus.OK.value()) + ); + //아티클 단건 조회에 좋아요 여부가 추가되면 단건 조회로 likes 여부까지 검증해보기 } } diff --git a/backend/src/acceptanceTest/resources/wooteco/prolog/article.feature b/backend/src/acceptanceTest/resources/wooteco/prolog/article.feature index 631295ce9..0c21cddc5 100644 --- a/backend/src/acceptanceTest/resources/wooteco/prolog/article.feature +++ b/backend/src/acceptanceTest/resources/wooteco/prolog/article.feature @@ -31,3 +31,8 @@ Feature: 아티클 관련 기능 Given 아티클이 작성되어 있고 When 1번 아티클에 북마크 요청을 보내면 Then 아티클에 북마크가 등록된다 + + Scenario: 아티클에 좋아요를 등록하기 + Given 아티클이 작성되어 있고 + When 1번 아티클에 좋아요 요청을 보내면 + Then 아티클에 좋아요가 등록된다 diff --git a/backend/src/documentation/adoc/article.adoc b/backend/src/documentation/adoc/article.adoc index 4c913ca77..052ed0ea2 100644 --- a/backend/src/documentation/adoc/article.adoc +++ b/backend/src/documentation/adoc/article.adoc @@ -10,3 +10,13 @@ include::{snippets}/article/bookmark/http-request.adoc[] ==== Response include::{snippets}/article/bookmark/http-response.adoc[] + +=== 아티클 좋아요 추가 + +==== Request + +include::{snippets}/article/likes/http-request.adoc[] + +==== Response + +include::{snippets}/article/likes/http-response.adoc[] diff --git a/backend/src/documentation/java/wooteco/prolog/docu/ArticleDocumentation.java b/backend/src/documentation/java/wooteco/prolog/docu/ArticleDocumentation.java index e872f5074..6aaac171b 100644 --- a/backend/src/documentation/java/wooteco/prolog/docu/ArticleDocumentation.java +++ b/backend/src/documentation/java/wooteco/prolog/docu/ArticleDocumentation.java @@ -12,6 +12,7 @@ import wooteco.prolog.article.application.ArticleService; import wooteco.prolog.article.ui.ArticleBookmarkRequest; import wooteco.prolog.article.ui.ArticleController; +import wooteco.prolog.article.ui.ArticleLikesRequest; @WebMvcTest(controllers = ArticleController.class) public class ArticleDocumentation extends NewDocumentation { @@ -28,7 +29,7 @@ public class ArticleDocumentation extends NewDocumentation { .header("Authorization", "Bearer " + accessToken) .contentType(APPLICATION_JSON) .body(bookmarkRequest) - .when().put("/articles/{bookmark-id}/bookmark", 1L) + .when().put("/articles/{article-id}/bookmark", 1L) .then().log().all(); //then @@ -37,4 +38,23 @@ public class ArticleDocumentation extends NewDocumentation { //docs response.apply(document("article/bookmark")); } + + @Test + void 아티클에_좋아요를_변경한다() { + //given, when + final ArticleLikesRequest articleLikesRequest = new ArticleLikesRequest(true); + + final ValidatableMockMvcResponse response = given + .header("Authorization", "Bearer " + accessToken) + .contentType(APPLICATION_JSON) + .body(articleLikesRequest) + .when().put("/articles/{article-id}/like", 1L) + .then().log().all(); + + //then + response.expect(status().isOk()); + + //docs + response.apply(document("article/like")); + } } diff --git a/backend/src/main/java/wooteco/prolog/article/application/ArticleService.java b/backend/src/main/java/wooteco/prolog/article/application/ArticleService.java index 55ec503ce..abefe800c 100644 --- a/backend/src/main/java/wooteco/prolog/article/application/ArticleService.java +++ b/backend/src/main/java/wooteco/prolog/article/application/ArticleService.java @@ -1,5 +1,9 @@ package wooteco.prolog.article.application; +import static java.util.stream.Collectors.toList; +import static wooteco.prolog.common.exception.BadRequestCode.ARTICLE_NOT_FOUND_EXCEPTION; + +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -14,12 +18,6 @@ import wooteco.prolog.member.application.MemberService; import wooteco.prolog.member.domain.Member; -import java.util.List; - -import static java.lang.Boolean.TRUE; -import static java.util.stream.Collectors.toList; -import static wooteco.prolog.common.exception.BadRequestCode.ARTICLE_NOT_FOUND_EXCEPTION; - @RequiredArgsConstructor @Service @Transactional(readOnly = true) @@ -63,27 +61,33 @@ public void delete(final Long id, final LoginMember loginMember) { @Transactional public void bookmarkArticle(final Long id, final LoginMember loginMember, - final Boolean checked) { - final Article article = articleRepository.findFetchById(id) + final Boolean isBookmark) { + final Article article = articleRepository.findFetchBookmarkById(id) .orElseThrow(() -> new BadRequestException(ARTICLE_NOT_FOUND_EXCEPTION)); final Member member = memberService.findById(loginMember.getId()); + article.setBookmark(member, isBookmark); + } - if (TRUE.equals(checked)) { - article.addBookmark(member); - } else { - article.removeBookmark(member); - } + @Transactional + public void likeArticle(final Long id, final LoginMember loginMember, final Boolean isLike) { + final Article article = articleRepository.findFetchLikeById(id) + .orElseThrow(() -> new BadRequestException(ARTICLE_NOT_FOUND_EXCEPTION)); + final Member member = memberService.findById(loginMember.getId()); + article.setLike(member, isLike); } - public List getFilteredArticles(final LoginMember member, final ArticleFilterType course, final boolean onlyBookmarked) { + public List getFilteredArticles(final LoginMember member, + final ArticleFilterType course, + final boolean onlyBookmarked) { if (member.isMember() && onlyBookmarked) { - return articleRepository.findArticlesByCourseAndMember(course.getGroupName(), member.getId()).stream() - .map(article -> ArticleResponse.of(article,member.getId())) + return articleRepository.findArticlesByCourseAndMember(course.getGroupName(), + member.getId()).stream() + .map(article -> ArticleResponse.of(article, member.getId())) .collect(toList()); } return articleRepository.findArticlesByCourse(course.getGroupName()).stream() - .map(article -> ArticleResponse.of(article,member.getId())) + .map(article -> ArticleResponse.of(article, member.getId())) .collect(toList()); } } diff --git a/backend/src/main/java/wooteco/prolog/article/domain/Article.java b/backend/src/main/java/wooteco/prolog/article/domain/Article.java index e115c85f0..be1c9ac0d 100644 --- a/backend/src/main/java/wooteco/prolog/article/domain/Article.java +++ b/backend/src/main/java/wooteco/prolog/article/domain/Article.java @@ -1,5 +1,7 @@ package wooteco.prolog.article.domain; +import static java.lang.Boolean.TRUE; + import java.time.LocalDateTime; import javax.persistence.Embedded; import javax.persistence.Entity; @@ -45,6 +47,9 @@ public class Article { @Embedded private ArticleBookmarks articleBookmarks; + @Embedded + private ArticleLikes articleLikes; + @CreatedDate private LocalDateTime createdAt; @@ -54,6 +59,7 @@ public Article(final Member member, final Title title, final Url url, final Imag this.url = url; this.imageUrl = imageUrl; this.articleBookmarks = new ArticleBookmarks(); + this.articleLikes = new ArticleLikes(); } public void validateOwner(final Member member) { @@ -67,12 +73,37 @@ public void update(final String title, final String url) { this.url = new Url(url); } - public void addBookmark(final Member member) { + public void setBookmark(final Member member, final Boolean isBookmark) { + if (TRUE.equals(isBookmark)) { + addBookmark(member); + } else { + removeBookmark(member); + } + } + + private void addBookmark(final Member member) { final ArticleBookmark articleBookmark = new ArticleBookmark(this, member.getId()); articleBookmarks.addBookmark(articleBookmark); } - public void removeBookmark(final Member member) { + private void removeBookmark(final Member member) { articleBookmarks.removeBookmark(member.getId()); } + + public void setLike(final Member member, final Boolean isLike) { + if (TRUE.equals(isLike)) { + addLike(member); + } else { + removeLike(member); + } + } + + private void addLike(final Member member) { + final ArticleLike articleLike = new ArticleLike(this, member.getId()); + articleLikes.addLike(articleLike); + } + + private void removeLike(final Member member) { + articleLikes.removeLike(member.getId()); + } } diff --git a/backend/src/main/java/wooteco/prolog/article/domain/ArticleLike.java b/backend/src/main/java/wooteco/prolog/article/domain/ArticleLike.java new file mode 100644 index 000000000..6748ff43c --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/article/domain/ArticleLike.java @@ -0,0 +1,43 @@ +package wooteco.prolog.article.domain; + +import java.util.Objects; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "article_like") +public class ArticleLike { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "article_id") + private Article article; + + private Long memberId; + + private ArticleLike(final Long id, final Article article, final Long memberId) { + this.id = id; + this.article = article; + this.memberId = memberId; + } + + public ArticleLike(final Article article, final Long memberId) { + this(null, article, memberId); + } + + public boolean isOwner(final Long memberId) { + return Objects.equals(this.memberId, memberId); + } +} diff --git a/backend/src/main/java/wooteco/prolog/article/domain/ArticleLikes.java b/backend/src/main/java/wooteco/prolog/article/domain/ArticleLikes.java new file mode 100644 index 000000000..5a919ebb0 --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/article/domain/ArticleLikes.java @@ -0,0 +1,36 @@ +package wooteco.prolog.article.domain; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Embeddable; +import javax.persistence.OneToMany; +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; + +@Embeddable +public class ArticleLikes { + + @OneToMany(mappedBy = "article") + @Cascade(value = {CascadeType.PERSIST, CascadeType.DELETE}) + private List articleLikes; + + public ArticleLikes() { + this.articleLikes = new ArrayList<>(); + } + + public void addLike(final ArticleLike articleLike) { + articleLikes.add(articleLike); + } + + public void removeLike(final Long memberId) { + articleLikes.stream() + .filter(like -> like.isOwner(memberId)) + .findAny() + .ifPresent(like -> articleLikes.remove(like)); + } + + public boolean isAlreadyLike(final Long memberId) { + return articleLikes.stream() + .anyMatch(like -> like.isOwner(memberId)); + } +} diff --git a/backend/src/main/java/wooteco/prolog/article/domain/repository/ArticleRepository.java b/backend/src/main/java/wooteco/prolog/article/domain/repository/ArticleRepository.java index 4681d5a1f..1f4adc33d 100644 --- a/backend/src/main/java/wooteco/prolog/article/domain/repository/ArticleRepository.java +++ b/backend/src/main/java/wooteco/prolog/article/domain/repository/ArticleRepository.java @@ -13,7 +13,10 @@ public interface ArticleRepository extends JpaRepository { List
findAllByOrderByCreatedAtDesc(); @Query("select a from Article a join fetch a.articleBookmarks where a.id = :id") - Optional
findFetchById(@Param("id") final Long id); + Optional
findFetchBookmarkById(@Param("id") final Long id); + + @Query("select a from Article a join fetch a.articleLikes where a.id = :id") + Optional
findFetchLikeById(@Param("id") final Long id); @Query("SELECT DISTINCT a FROM Article a " + "JOIN GroupMember gm ON a.member.id = gm.member.id " + diff --git a/backend/src/main/java/wooteco/prolog/article/ui/ArticleController.java b/backend/src/main/java/wooteco/prolog/article/ui/ArticleController.java index 2ac381fd9..91ade747e 100644 --- a/backend/src/main/java/wooteco/prolog/article/ui/ArticleController.java +++ b/backend/src/main/java/wooteco/prolog/article/ui/ArticleController.java @@ -56,6 +56,14 @@ public ResponseEntity bookmarkArticle(@PathVariable final Long id, return ResponseEntity.ok().build(); } + @PutMapping("/{id}/like") + public ResponseEntity likeArticle(@PathVariable final Long id, + @AuthMemberPrincipal final LoginMember member, + @RequestBody final ArticleLikesRequest request) { + articleService.likeArticle(id, member, request.getLike()); + return ResponseEntity.ok().build(); + } + @GetMapping public ResponseEntity> getFilteredArticles(@AuthMemberPrincipal final LoginMember member, @RequestParam("course") final ArticleFilterType course, diff --git a/backend/src/main/java/wooteco/prolog/article/ui/ArticleLikesRequest.java b/backend/src/main/java/wooteco/prolog/article/ui/ArticleLikesRequest.java new file mode 100644 index 000000000..9dce50790 --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/article/ui/ArticleLikesRequest.java @@ -0,0 +1,15 @@ +package wooteco.prolog.article.ui; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class ArticleLikesRequest { + + private final Boolean like; + + public ArticleLikesRequest() { + this(null); + } +} diff --git a/backend/src/main/resources/db/migration/prod/V6__create_table_article_bookmark.sql b/backend/src/main/resources/db/migration/prod/V6__create_table_article_bookmark.sql index fc5b4f786..20062f012 100644 --- a/backend/src/main/resources/db/migration/prod/V6__create_table_article_bookmark.sql +++ b/backend/src/main/resources/db/migration/prod/V6__create_table_article_bookmark.sql @@ -2,7 +2,9 @@ create table if not exists prolog.article_bookmark ( id bigint auto_increment primary key, article_id bigint not null, - member_id bigint not null + member_id bigint not null, + foreign key (member_id) references prolog.member (id), + foreign key (article_id) references prolog.article (id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; diff --git a/backend/src/main/resources/db/migration/prod/V7__create_table_article_like.sql b/backend/src/main/resources/db/migration/prod/V7__create_table_article_like.sql new file mode 100644 index 000000000..59700e066 --- /dev/null +++ b/backend/src/main/resources/db/migration/prod/V7__create_table_article_like.sql @@ -0,0 +1,10 @@ +create table if not exists prolog.article_like +( + id bigint auto_increment primary key, + article_id bigint not null, + member_id bigint not null, + foreign key (member_id) references prolog.member (id), + foreign key (article_id) references prolog.article (id) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_0900_ai_ci; diff --git a/backend/src/test/java/wooteco/prolog/article/application/ArticleServiceTest.java b/backend/src/test/java/wooteco/prolog/article/application/ArticleServiceTest.java index 1d5c4a366..0512583d5 100644 --- a/backend/src/test/java/wooteco/prolog/article/application/ArticleServiceTest.java +++ b/backend/src/test/java/wooteco/prolog/article/application/ArticleServiceTest.java @@ -11,6 +11,7 @@ import wooteco.prolog.article.domain.Article; import wooteco.prolog.article.domain.ArticleBookmarks; import wooteco.prolog.article.domain.ArticleFilterType; +import wooteco.prolog.article.domain.ArticleLikes; import wooteco.prolog.article.domain.ImageUrl; import wooteco.prolog.article.domain.Title; import wooteco.prolog.article.domain.Url; @@ -204,7 +205,8 @@ void add() { final Long articleId = 3L; final LoginMember loginMember = new LoginMember(member.getId(), MEMBER); - when(articleRepository.findFetchById(articleId)).thenReturn(Optional.of(article)); + when(articleRepository.findFetchBookmarkById(articleId)).thenReturn( + Optional.of(article)); when(memberService.findById(member.getId())).thenReturn(member); //when @@ -227,7 +229,8 @@ void remove() { final Long articleId = 3L; final LoginMember loginMember = new LoginMember(member.getId(), MEMBER); - when(articleRepository.findFetchById(articleId)).thenReturn(Optional.of(article)); + when(articleRepository.findFetchBookmarkById(articleId)).thenReturn( + Optional.of(article)); when(memberService.findById(member.getId())).thenReturn(member); //when @@ -240,6 +243,57 @@ void remove() { } } + @Nested + @DisplayName("아티클의 좋아요 상태를 바꿀 수 있다.") + class likeArticle { + + @DisplayName("아티클에 좋아요를 추가한다.") + @Test + void add() { + //given + final Member member = new Member(1L, "userName", "nickName", + CREW, 1L, "imageUrl"); + final Article article = new Article(member, new Title("brownTitle"), + new Url("brownUrl"), new ImageUrl("imageUrl")); + final Long articleId = 3L; + final LoginMember loginMember = new LoginMember(member.getId(), MEMBER); + + when(articleRepository.findFetchLikeById(articleId)).thenReturn(Optional.of(article)); + when(memberService.findById(member.getId())).thenReturn(member); + + //when + articleService.likeArticle(articleId, loginMember, true); + + //then + final ArticleLikes articleBookmarks = article.getArticleLikes(); + assertThat(articleBookmarks.isAlreadyLike(member.getId())) + .isTrue(); + } + + @DisplayName("아티클의 좋아요를 삭제한다.") + @Test + void remove() { + //given + final Member member = new Member(1L, "userName", "nickName", + CREW, 1L, "imageUrl"); + final Article article = new Article(member, new Title("brownTitle"), + new Url("brownUrl"), new ImageUrl("imageUrl")); + final Long articleId = 3L; + final LoginMember loginMember = new LoginMember(member.getId(), MEMBER); + + when(articleRepository.findFetchLikeById(articleId)).thenReturn(Optional.of(article)); + when(memberService.findById(member.getId())).thenReturn(member); + + //when + articleService.likeArticle(articleId, loginMember, false); + + //then + final ArticleLikes articleBookmarks = article.getArticleLikes(); + assertThat(articleBookmarks.isAlreadyLike(member.getId())) + .isFalse(); + } + } + @DisplayName("비로그인 사용자가 백엔드 아티클을 필터링 한다.") @Test void filter() { diff --git a/backend/src/test/java/wooteco/prolog/article/domain/ArticleLikeTest.java b/backend/src/test/java/wooteco/prolog/article/domain/ArticleLikeTest.java new file mode 100644 index 000000000..c0527dda4 --- /dev/null +++ b/backend/src/test/java/wooteco/prolog/article/domain/ArticleLikeTest.java @@ -0,0 +1,30 @@ +package wooteco.prolog.article.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import wooteco.prolog.member.domain.Member; +import wooteco.prolog.member.domain.Role; + +class ArticleLikeTest { + + @DisplayName("memberId가 동일한지 확인") + @Test + void isOwner() { + //given + final Member member = new Member(11L, "username", "nickname", Role.CREW, 101L, "https://"); + final Title title = new Title("title"); + final Url url = new Url("url"); + final ImageUrl imageUrl = new ImageUrl("imageUrl"); + final Article article = new Article(member, title, url, imageUrl); + final ArticleLike articleLike = new ArticleLike(article, member.getId()); + + //when + final Boolean actual = articleLike.isOwner(member.getId()); + + //then + assertThat(actual) + .isTrue(); + } +} diff --git a/backend/src/test/java/wooteco/prolog/article/domain/ArticleLikesTest.java b/backend/src/test/java/wooteco/prolog/article/domain/ArticleLikesTest.java new file mode 100644 index 000000000..d65d79811 --- /dev/null +++ b/backend/src/test/java/wooteco/prolog/article/domain/ArticleLikesTest.java @@ -0,0 +1,76 @@ +package wooteco.prolog.article.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import wooteco.prolog.member.domain.Member; +import wooteco.prolog.member.domain.Role; + +class ArticleLikesTest { + + private Member member; + private Title title; + private Url url; + private ImageUrl imageUrl; + + @BeforeEach + void setUp() { + member = new Member(11L, "username", "nickname", Role.CREW, 101L, "https://"); + title = new Title("title"); + url = new Url("url"); + imageUrl = new ImageUrl("imageUrl"); + } + + @Test + @DisplayName("ArticleBookmark를 추가할 수 있다.") + void addArticleLike() { + //given + final ArticleLikes articleLikes = new ArticleLikes(); + final Article article = new Article(member, title, url, imageUrl); + final ArticleLike articleLike = new ArticleLike(article, member.getId()); + + //when + articleLikes.addLike(articleLike); + + //then + assertThat(articleLikes.isAlreadyLike(member.getId())) + .isTrue(); + } + + @Test + @DisplayName("ArticleBookmark를 삭제할 수 있다,") + void removeArticleLike() { + //given + final ArticleLikes articleLikes = new ArticleLikes(); + final Article article = new Article(member, title, url, imageUrl); + final ArticleLike articleLike = new ArticleLike(article, member.getId()); + articleLikes.addLike(articleLike); + + //when + articleLikes.removeLike(member.getId()); + + //then + assertThat(articleLikes.isAlreadyLike(member.getId())) + .isFalse(); + } + + @Test + @DisplayName("ArticleBookmarks에 memberId를 넘겨서 해당 member가 아티클을 북마크했는지 확인한다.") + void isAlreadyLike() { + //given + final ArticleLikes articleLikes = new ArticleLikes(); + final Article article = new Article(member, title, url, imageUrl); + final ArticleLike articleLike = new ArticleLike(article, member.getId()); + articleLikes.addLike(articleLike); + + //when + final Boolean actual = articleLikes.isAlreadyLike(member.getId()); + + //then + assertThat(actual) + .isTrue(); + } + +} diff --git a/backend/src/test/java/wooteco/prolog/article/domain/ArticleTest.java b/backend/src/test/java/wooteco/prolog/article/domain/ArticleTest.java index 44f9c8cd8..5f6bbedca 100644 --- a/backend/src/test/java/wooteco/prolog/article/domain/ArticleTest.java +++ b/backend/src/test/java/wooteco/prolog/article/domain/ArticleTest.java @@ -7,6 +7,7 @@ import joptsimple.internal.Strings; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import wooteco.prolog.common.exception.BadRequestException; import wooteco.prolog.member.domain.Member; @@ -98,38 +99,83 @@ void update_invalidUrl() { .isInstanceOf(BadRequestException.class); } - @DisplayName("멤버가 아티클을 북마크로 등록한다.") - @Test - void addBookmark() { - //given - final Article article = new Article(member, title, url, imageUrl); + @Nested + @DisplayName("멤버가 아티클의 북마크값을 세팅한다.") + class setBookmark { - //when - article.addBookmark(member); + @DisplayName("멤버가 아티클을 북마크로 등록한다.") + @Test + void addBookmark() { + //given + final Article article = new Article(member, title, url, imageUrl); - //then - final ArticleBookmarks articleBookmarks = article.getArticleBookmarks(); - final boolean contains = articleBookmarks.containBookmark(member.getId()); + //when + article.setBookmark(member, true); + + //then + final ArticleBookmarks articleBookmarks = article.getArticleBookmarks(); + final boolean contains = articleBookmarks.containBookmark(member.getId()); + + assertThat(contains) + .isTrue(); + } + + @DisplayName("멤버가 아티클의 북마크를 해제한다.") + @Test + void removeBookmark() { + //given + final Article article = new Article(member, title, url, imageUrl); + article.setBookmark(member, true); + + //when + article.setBookmark(member, false); + + //then + final ArticleBookmarks articleBookmarks = article.getArticleBookmarks(); + final boolean contains = articleBookmarks.containBookmark(member.getId()); - assertThat(contains) - .isTrue(); + assertThat(contains) + .isFalse(); + } } - @DisplayName("멤버가 아티클을 북마크로 등록한다.") - @Test - void removeBookmark() { - //given - final Article article = new Article(member, title, url, imageUrl); - article.addBookmark(member); + @Nested + @DisplayName("멤버가 아티클의 좋아요 값을 세팅한다.") + class setLike { - //when - article.removeBookmark(member); + @DisplayName("멤버가 아티클 좋아요를 추가한다.") + @Test + void addLike() { + //given + final Article article = new Article(member, title, url, imageUrl); - //then - final ArticleBookmarks articleBookmarks = article.getArticleBookmarks(); - final boolean contains = articleBookmarks.containBookmark(member.getId()); + //when + article.setLike(member, true); + + //then + final ArticleLikes articleLike = article.getArticleLikes(); + final boolean alreadyLike = articleLike.isAlreadyLike(member.getId()); + + assertThat(alreadyLike) + .isTrue(); + } + + @DisplayName("멤버가 아티클 좋아요를 해제한다.") + @Test + void removeLike() { + //given + final Article article = new Article(member, title, url, imageUrl); + article.setLike(member, true); + + //when + article.setLike(member, false); + + //then + final ArticleLikes articleLike = article.getArticleLikes(); + final boolean alreadyLike = articleLike.isAlreadyLike(member.getId()); - assertThat(contains) - .isFalse(); + assertThat(alreadyLike) + .isFalse(); + } } }