From e5b12f9427b64bd723474af5c3ebfdcd8cfd4c66 Mon Sep 17 00:00:00 2001 From: JeongSW123 <123189509+JeongSW123@users.noreply.github.com> Date: Sat, 27 Jun 2026 17:28:20 +0900 Subject: [PATCH] =?UTF-8?q?feat(posts):=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=97=94=EB=93=9C=ED=8F=AC=EC=9D=B8?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/posts/views.py | 3 ++- tests/test_posts.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/apps/posts/views.py b/apps/posts/views.py index 723a6d9..4f96c93 100644 --- a/apps/posts/views.py +++ b/apps/posts/views.py @@ -47,12 +47,13 @@ def get_queryset(self): ) -class PostDetailView(generics.RetrieveAPIView): +class PostDetailView(generics.RetrieveDestroyAPIView): serializer_class = PostSerializer permission_classes = (IsAuthenticated,) lookup_field = "post_id" def get_queryset(self): + # 본인 캐릭터의 게시물만 조회·삭제할 수 있다(DELETE 시 댓글·답글은 CASCADE). return _POST_QUERYSET.filter(character__user=self.request.user) def get_serializer_context(self): diff --git a/tests/test_posts.py b/tests/test_posts.py index cde4dbe..377d8a6 100644 --- a/tests/test_posts.py +++ b/tests/test_posts.py @@ -109,6 +109,36 @@ def test_post_detail_authenticated(auth_client: APIClient, post: Post) -> None: assert response.json()["content"] == "테스트 게시글" +# 본인 게시글 삭제 성공 시 204 + 게시글·댓글이 함께 삭제(CASCADE)되는지 확인 +@pytest.mark.django_db +def test_post_delete_authenticated( + auth_client: APIClient, user: User, post: Post +) -> None: + comment = Comment.objects.create(post=post, user=user, content="댓글") + + response = auth_client.delete(f"/api/v1/posts/{post.post_id}/") + + assert response.status_code == 204 + assert not Post.objects.filter(post_id=post.post_id).exists() + assert not Comment.objects.filter(pk=comment.pk).exists() # CASCADE 로 함께 삭제 + + +# 다른 사용자의 게시글은 삭제할 수 없다(404, 게시글 유지) +@pytest.mark.django_db +def test_post_delete_other_user_forbidden(auth_client: APIClient) -> None: + other_post = _make_other_user_post() + response = auth_client.delete(f"/api/v1/posts/{other_post.post_id}/") + assert response.status_code == 404 + assert Post.objects.filter(post_id=other_post.post_id).exists() + + +# 비로그인 상태에서 삭제 시 401 반환 확인 +@pytest.mark.django_db +def test_post_delete_unauthenticated(post: Post) -> None: + response = APIClient().delete(f"/api/v1/posts/{post.post_id}/") + assert response.status_code == 401 + + # 이사한 캐릭터의 게시물/답글에도 캐릭터 이미지 URL이 포함되는지 확인 @pytest.mark.django_db def test_post_detail_includes_inactive_character_images(