Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
urlpatterns = [
path("posts/", views.retrieve_post_list, name="retrieve_post_list"),
path("posts/<int:id>", views.retrieve_post_detail, name="retrieve_post_detail"),
path("posts/create", views.create_post, name="create_post"),
path("posts/<int:id>/put/update", views.update_post_with_put, name="update_post_with_put"),
path("posts/<int:id>/delete", views.delete_post, name="delete_post")
# path("posts/create", views.create_post, name="create_post"),
# path("posts/<int:id>/put/update", views.update_post_with_put, name="update_post_with_put"),
# path("posts/<int:id>/delete", views.delete_post, name="delete_post")
path("posts/<int:post_id>/comments", views.CommentListCreate.as_view(), name="comment_list_create"),
]
35 changes: 31 additions & 4 deletions django_girls_tutorial/step2/sehwa/djangogirls/blog/api/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import json
from django.http import JsonResponse
from django.utils import timezone
from django.views import View
from django.views.decorators.http import require_http_methods

from django.contrib.auth.models import User
from blog.models import Post
from blog.models import Post, Comment


def retrieve_post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by(
"published_date"
)
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by("published_date")

post_list = [
{
Expand Down Expand Up @@ -43,3 +42,31 @@ def retrieve_post_detail(request, id):
},
status=200,
)


class CommentListCreate(View):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CBV 쓴건 좋은 선택인거 같애~

def get(self, request, post_id):
try:
post = Post.objects.get(pk=post_id)
except Post.DoesNotExist:
return JsonResponse({"message": "post가 없습니다."}, status=404)

comments = Comment.objects.filter(post=post, created_date__lte=timezone.now()).order_by("created_date")
comment_list = [{"author": comment.author, "text": comment.text} for comment in comments]

return JsonResponse({"data": comment_list})
Comment on lines +55 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nipick,

Suggested change
comment_list = [{"author": comment.author, "text": comment.text} for comment in comments]
return JsonResponse({"data": comment_list})
return JsonResponse({"data": [{"author": comment.author, "text": comment.text} for comment in comments]})

변수 선언안해줘도 코드로 인지 가능해서 인라인해서 써줘도 될거 같애~


def post(self, request, post_id):
try:
post = Post.objects.get(pk=post_id)
except Post.DoesNotExist:
return JsonResponse({"message": "post가 없습니다."}, status=404)

body = request.POST
if not body["author"]:
return JsonResponse({"message": "author가 없습니다."}, status=400)
elif not body["text"]:
return JsonResponse({"message": "text가 없습니다."}, status=400)

comment = Comment.objects.create(post=post, author=body["author"], text=body["text"])
return JsonResponse({"data": {"post_id": post.id, "author": comment.author, "text": comment.text}}, status=201)
162 changes: 136 additions & 26 deletions django_girls_tutorial/step2/sehwa/djangogirls/blog/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.test import TestCase
from django.urls import reverse

from .models import Post
from .models import Post, Comment


class TestPostMixin:
Expand All @@ -20,25 +20,25 @@ def _create_post(author, title, text):
def _create_author(username, password):
return User.objects.create_superuser(username=username, password=password)

@staticmethod
def _create_comment_on_post(post, author, text):
return Comment.objects.create(post=post, author=author, text=text)


class TestPostList(TestPostMixin, TestCase):
def setUp(self):
super().setUp()

def test_list_with_count(self):
for i in range(10):
post = self._create_post(
author=self.author, title=f"test title-{i}", text=f"test text-{i}"
)
post = self._create_post(author=self.author, title=f"test title-{i}", text=f"test text-{i}")
post.publish()
response = self.client.get(reverse("retrieve_post_list"))
response_data = json.loads(response.content)["posts"]
self.assertEqual(len(response_data), 10)

def test_list_with_published_post(self):
post = self._create_post(
author=self.author, title="test title", text="test text"
)
post = self._create_post(author=self.author, title="test title", text="test text")
post.publish()
response = self.client.get(reverse("retrieve_post_list"))
response_data = json.loads(response.content)["posts"]
Expand All @@ -58,9 +58,7 @@ def setUp(self):
super().setUp()

def test_post_detail(self):
post = self._create_post(
author=self.author, title="test title", text="test text"
)
post = self._create_post(author=self.author, title="test title", text="test text")
post.publish()
response = self.client.get(reverse("retrieve_post_detail", kwargs={"id": 1}))
response_data = json.loads(response.content)["post"]
Expand Down Expand Up @@ -118,10 +116,14 @@ def setUp(self):

def test_post_update_with_put(self):
# Given: 업데이트 하기 위한 유효한 request body 값이 주어지고,
request_body_for_put_update = json.dumps({"author": self.author.id, "title": "test test title", "text": "test test text"})
request_body_for_put_update = json.dumps(
{"author": self.author.id, "title": "test test title", "text": "test test text"}
)

# When: 1번 post에 대한 업데이트 api를 호출 할 때,
response = self.client.put(reverse("update_post_with_put", kwargs={"id": self.post.id}), data=request_body_for_put_update)
response = self.client.put(
reverse("update_post_with_put", kwargs={"id": self.post.id}), data=request_body_for_put_update
)

# Then: 상태코드는 200이고,
self.assertEqual(response.status_code, 200)
Expand All @@ -135,15 +137,17 @@ def test_post_update_with_put(self):
self.assertEqual(response["title"], "test test title")
self.assertEqual(response["text"], "test test text")


def test_post_update_with_error_with_author_on_404(self):
# Given: 업데이트 하기 위한 유효하지 않은 author_id 값이 주어지고,
invalid_author_id = 123123123
request_body_for_put_update = json.dumps(
{"author": invalid_author_id, "title": "test test title", "text": "test test text"})
{"author": invalid_author_id, "title": "test test title", "text": "test test text"}
)

# When: 1번 post에 대한 업데이트 api를 호출 할 때,
response = self.client.put(reverse("update_post_with_put", kwargs={"id": self.post.id}), data=request_body_for_put_update)
response = self.client.put(
reverse("update_post_with_put", kwargs={"id": self.post.id}), data=request_body_for_put_update
)

# Then: 상태코드는 404이고,
self.assertEqual(response.status_code, 404)
Expand All @@ -159,11 +163,14 @@ def test_post_update_with_error_with_author_on_404(self):
def test_post_update_with_error_with_post_on_404(self):
# Given: 업데이트 하기 위한 유효하지 않은 post_id 값이 주어지고,
request_body_for_put_update = json.dumps(
{"author": self.author.id, "title": "test test title", "text": "test test text"})
{"author": self.author.id, "title": "test test title", "text": "test test text"}
)
invalid_post_id = 12345

# When: # When: 유효하지 않은 post에 대한 업데이트 api를 호출 할 때,
response = self.client.put(reverse("update_post_with_put", kwargs={"id": invalid_post_id}), data=request_body_for_put_update)
response = self.client.put(
reverse("update_post_with_put", kwargs={"id": invalid_post_id}), data=request_body_for_put_update
)

# Then: 상태코드는 404이고,
self.assertEqual(response.status_code, 404)
Expand All @@ -188,9 +195,7 @@ def test_delete_post(self):
post_id = self.post.id

# When: delete_post api 실행.
response = self.client.delete(
reverse("delete_post", kwargs={"id": post_id}), data=request_body
)
response = self.client.delete(reverse("delete_post", kwargs={"id": post_id}), data=request_body)

# Then: 실행 결과 상태코드 200 return.
self.assertEqual(response.status_code, 200)
Expand All @@ -204,9 +209,7 @@ def test_delete_post_with_invalid_post_id(self):
invalid_post_id = 9999999

# When: delete_post api 실행.
response = self.client.delete(
reverse("delete_post", kwargs={"id": invalid_post_id}), data=request_body
)
response = self.client.delete(reverse("delete_post", kwargs={"id": invalid_post_id}), data=request_body)

# Then: 실행결과 상태코드 403 여야 한다.
self.assertEqual(response.status_code, 403)
Expand All @@ -228,9 +231,7 @@ def test_delete_post_with_invalid_author_id(self):
post_id = self.post.id

# When: delete_post api 실행.
response = self.client.delete(
reverse("delete_post", kwargs={"id": post_id}), data=invalid_request_body
)
response = self.client.delete(reverse("delete_post", kwargs={"id": post_id}), data=invalid_request_body)
# Then: 실행결과 상태코드 404 여야 한다.
self.assertEqual(response.status_code, 404)

Expand All @@ -243,3 +244,112 @@ def test_delete_post_with_invalid_author_id(self):
# And: 응답 메세지가 유효하지 않은 사용자 id입니다. 여야 한다.
response = json.loads(response.content)
self.assertEqual(response["message"], "유효하지 않은 사용자 id입니다.")


class TestCommentList(TestPostMixin, TestCase):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굳 테스트 잘짰네~ ㅋㅋ 👍

def setUp(self):
super().setUp()
self.post = self._create_post(self.author, "test", "test text")

def test_comment_list_on_valid_post_with_comment_count(self):
# Given: 정상적으로 생성된 comment 10개, 유효한 post id
post_id = self.post.id
comment_count = 10
for i in range(comment_count):
comment = self._create_comment_on_post(self.post, f"author{i}", f"comment{i}")
comment.approve()
Comment on lines +258 to +260
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 extract method 할 수 있을 것 같애
* 다른 테스트들과 연관된 부분이 아니라서 굳이 뺄 필욘 없지만, 가독성 측면 혹은 나중에 혹시 재활용할 측면에서는 뺴는게 좋다고 생각함

...
def _create_comments_with_approve(self, comment_count):
    for i in range(comment_count):
        comment = self._create_comment_on_post(self.post, f"author{i}", f"comment{i}")
        comment.approve()
...


# When: comment_list_create api get 실행
response = self.client.get(reverse("comment_list_create", kwargs={"post_id": post_id}))

# Then: 실행결과 200, 댓글 갯수 10개여야 함.
response = json.loads(response.content)
self.assertEqual(comment_count, len(response["data"]))

def test_comment_list_on_invalid_post_id(self):
# Given: 유효하지 않은 post id
invalid_post_id = 9876

# When: comment_list_create api get 실행
response = self.client.get(reverse("comment_list_create", kwargs={"post_id": invalid_post_id}))

# Then: 실행결과 404여야 함.
self.assertEqual(response.status_code, 404)

# And: 메세지 응답이 post가 없습니다. 여야 함.
response = json.loads(response.content)
self.assertEqual(response["message"], "post가 없습니다.")


class TestCommentCreate(TestPostMixin, TestCase):
def setUp(self):
super().setUp()
self.post = self._create_post(self.author, "test", "test")

def test_comment_create(self):
# Given: 유효한 post id, comment data
post_id = self.post.id
request_body = {"author": "test author", "text": "test text"}

# When: comment_list_create api post 실행
response = self.client.post(reverse("comment_list_create", kwargs={"post_id": post_id}), data=request_body)

# Then: 정상적으로 등록. 상태코드 201
self.assertEqual(response.status_code, 201)

# And: 응답에서 comment의 post id, author, text를 리턴.
response = json.loads(response.content)["data"]
self.assertEqual(response["post_id"], post_id)
self.assertEqual(response["author"], "test author")
self.assertEqual(response["text"], "test text")

def test_comment_create_with_invalid_post_id(self):
# Given: 유효하지 않은 post id
invalid_post_id = 9876
request_body = {"author": "test author", "text": "test text"}

# When: comment_list_create api post 실행
response = self.client.post(
reverse("comment_list_create", kwargs={"post_id": invalid_post_id}), data=request_body
)

# Then: comment 등록 실패, 상태코드 404
self.assertEqual(response.status_code, 404)

# And: 메세지 응답이 post가 없습니다. 여야 함.
response = json.loads(response.content)
self.assertEqual(response["message"], "post가 없습니다.")

def test_comment_create_without_author(self):
# Given: author를 입력받지 않음.
post_id = self.post.id
invalid_request_body = {"author": "", "text": "test text"}

# When: comment_list_create api post 실행
response = self.client.post(
reverse("comment_list_create", kwargs={"post_id": post_id}), data=invalid_request_body
)

# Then: comment 등록 실패, 상태코드 400
self.assertEqual(response.status_code, 400)

# And: 메세지 응답이 author가 없습니다. 여야 함.
response = json.loads(response.content)
self.assertEqual(response["message"], "author가 없습니다.")

def test_comment_create_without_text(self):
# Given: text를 입력받지 않음.
post_id = self.post.id
invalid_request_body = {"author": "test author", "text": ""}

# When: comment_list_create api post 실행
response = self.client.post(
reverse("comment_list_create", kwargs={"post_id": post_id}), data=invalid_request_body
)

# Then: comment 등록 실패, 상태코드 400
self.assertEqual(response.status_code, 400)

# And: 메세지 응답이 text가 없습니다. 여야 함.
response = json.loads(response.content)
self.assertEqual(response["message"], "text가 없습니다.")