diff --git a/src/main/java/io/spring/api/ArticleFavoriteApi.java b/src/main/java/io/spring/api/ArticleFavoriteApi.java index 147db07..e966ba7 100644 --- a/src/main/java/io/spring/api/ArticleFavoriteApi.java +++ b/src/main/java/io/spring/api/ArticleFavoriteApi.java @@ -11,6 +11,7 @@ import io.spring.core.user.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -43,8 +44,18 @@ public class ArticleFavoriteApi { return responseArticleData(articleQueryService.findBySlug(slug, user).get()); } + @DeleteMapping + public ResponseEntity unfavoriteArticle(@PathVariable("slug") String slug, + @AuthenticationPrincipal User user) { + Article article = getArticle(slug); + articleFavoriteRepository.find(article.getId(), user.getId()).ifPresent(favorite -> { + articleFavoriteRepository.remove(favorite); + }); + return responseArticleData(articleQueryService.findBySlug(slug, user).get()); + } + private ResponseEntity> responseArticleData(final ArticleData articleData) { - return ResponseEntity.status(201).body(new HashMap() {{ + return ResponseEntity.ok(new HashMap() {{ put("article", articleData); }}); } diff --git a/src/main/java/io/spring/core/favorite/ArticleFavoriteRepository.java b/src/main/java/io/spring/core/favorite/ArticleFavoriteRepository.java index 6ab0e6b..7e469cd 100644 --- a/src/main/java/io/spring/core/favorite/ArticleFavoriteRepository.java +++ b/src/main/java/io/spring/core/favorite/ArticleFavoriteRepository.java @@ -1,5 +1,11 @@ package io.spring.core.favorite; +import java.util.Optional; + public interface ArticleFavoriteRepository { void save(ArticleFavorite articleFavorite); + + Optional find(String articleId, String userId); + + void remove(ArticleFavorite favorite); } diff --git a/src/main/java/io/spring/infrastructure/favorite/ArticleFavoriteMapper.java b/src/main/java/io/spring/infrastructure/favorite/ArticleFavoriteMapper.java index 153ad3b..84aea60 100644 --- a/src/main/java/io/spring/infrastructure/favorite/ArticleFavoriteMapper.java +++ b/src/main/java/io/spring/infrastructure/favorite/ArticleFavoriteMapper.java @@ -8,7 +8,9 @@ import org.springframework.stereotype.Component; @Mapper @Component public interface ArticleFavoriteMapper { - boolean find(@Param("articleFavorite") ArticleFavorite articleFavorite); + ArticleFavorite find(@Param("articleId") String articleId, @Param("userId") String userId); void insert(@Param("articleFavorite") ArticleFavorite articleFavorite); + + void delete(@Param("favorite") ArticleFavorite favorite); } diff --git a/src/main/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepository.java b/src/main/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepository.java index 1550b48..4f0eccd 100644 --- a/src/main/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepository.java +++ b/src/main/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepository.java @@ -5,6 +5,8 @@ import io.spring.core.favorite.ArticleFavoriteRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public class MyBatisArticleFavoriteRepository implements ArticleFavoriteRepository { private ArticleFavoriteMapper mapper; @@ -16,8 +18,18 @@ public class MyBatisArticleFavoriteRepository implements ArticleFavoriteReposito @Override public void save(ArticleFavorite articleFavorite) { - if (!mapper.find(articleFavorite)) { + if (mapper.find(articleFavorite.getArticleId(), articleFavorite.getUserId()) != null) { mapper.insert(articleFavorite); } } + + @Override + public Optional find(String articleId, String userId) { + return Optional.ofNullable(mapper.find(articleId, userId)); + } + + @Override + public void remove(ArticleFavorite favorite) { + mapper.delete(favorite); + } } diff --git a/src/main/resources/mapper/ArticleFavoriteMapper.xml b/src/main/resources/mapper/ArticleFavoriteMapper.xml index 4dce7da..7c1e48b 100644 --- a/src/main/resources/mapper/ArticleFavoriteMapper.xml +++ b/src/main/resources/mapper/ArticleFavoriteMapper.xml @@ -4,7 +4,18 @@ insert into article_favorites (article_id, user_id) values (#{articleFavorite.articleId}, #{articleFavorite.userId}) - + select + AF.article_id articleFavoriteArticleId, + AF.user_id articleFavoriteUserId + from article_favorites AF + where AF.article_id = #{articleId} and AF.user_id = #{userId} + + + + \ No newline at end of file diff --git a/src/test/java/io/spring/api/ArticleFavoriteApiTest.java b/src/test/java/io/spring/api/ArticleFavoriteApiTest.java index 735a00c..d969c9a 100644 --- a/src/test/java/io/spring/api/ArticleFavoriteApiTest.java +++ b/src/test/java/io/spring/api/ArticleFavoriteApiTest.java @@ -8,6 +8,7 @@ import io.spring.application.profile.ProfileData; import io.spring.core.article.Article; import io.spring.core.article.ArticleRepository; import io.spring.core.article.Tag; +import io.spring.core.favorite.ArticleFavorite; import io.spring.core.favorite.ArticleFavoriteRepository; import io.spring.core.user.User; import org.junit.Before; @@ -23,7 +24,9 @@ import java.util.stream.Collectors; import static io.restassured.RestAssured.given; import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -86,7 +89,23 @@ public class ArticleFavoriteApiTest extends TestWithCurrentUser { .post("/articles/{slug}/favorite", article.getSlug()) .prettyPeek() .then() - .statusCode(201) + .statusCode(200) .body("article.id", equalTo(article.getId())); + + verify(articleFavoriteRepository).save(any()); + } + + @Test + public void should_unfavorite_an_article_success() throws Exception { + when(articleFavoriteRepository.find(eq(article.getId()), eq(user.getId()))).thenReturn(Optional.of(new ArticleFavorite(article.getId(), user.getId()))); + given() + .header("Authorization", "Token " + token) + .when() + .delete("/articles/{slug}/favorite", article.getSlug()) + .prettyPeek() + .then() + .statusCode(200) + .body("article.id", equalTo(article.getId())); + verify(articleFavoriteRepository).remove(new ArticleFavorite(article.getId(), user.getId())); } } diff --git a/src/test/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepositoryTest.java b/src/test/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepositoryTest.java index 99853d5..f0131e9 100644 --- a/src/test/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepositoryTest.java +++ b/src/test/java/io/spring/infrastructure/favorite/MyBatisArticleFavoriteRepositoryTest.java @@ -26,6 +26,14 @@ public class MyBatisArticleFavoriteRepositoryTest { public void should_save_and_fetch_articleFavorite_success() throws Exception { ArticleFavorite articleFavorite = new ArticleFavorite("123", "456"); articleFavoriteRepository.save(articleFavorite); - assertThat(articleFavoriteMapper.find(articleFavorite), is(true)); + assertThat(articleFavoriteMapper.find(articleFavorite.getArticleId(), articleFavorite.getUserId()), is(true)); + } + + @Test + public void should_remove_favorite_success() throws Exception { + ArticleFavorite articleFavorite = new ArticleFavorite("123", "456"); + articleFavoriteRepository.save(articleFavorite); + articleFavoriteRepository.remove(articleFavorite); + assertThat(articleFavoriteRepository.find("123", "456").isPresent(), is(false)); } } \ No newline at end of file