Skip to content

Commit

Permalink
Merge pull request #20 from andela/ft-favorite-unfavorite-articles-16…
Browse files Browse the repository at this point in the history
…2948847

#162948847 Favorite and Unfavorite Articles
  • Loading branch information
Ignatius Ukwuoma committed Jan 28, 2019
2 parents d1e6e4d + 9ee7f17 commit e7199d9
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 43 deletions.
25 changes: 25 additions & 0 deletions authors/apps/articles/migrations/0010_favoritearticle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 2.1.4 on 2019-01-23 08:10

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('articles', '0009_auto_20190121_0754'),
]

operations = [
migrations.CreateModel(
name='FavoriteArticle',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('body', models.BooleanField(default=False)),
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='article', to='articles.Article')),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='author', to=settings.AUTH_USER_MODEL)),
],
),
]
18 changes: 18 additions & 0 deletions authors/apps/articles/migrations/0011_auto_20190123_0813.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.1.4 on 2019-01-23 08:13

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('articles', '0010_favoritearticle'),
]

operations = [
migrations.RenameField(
model_name='favoritearticle',
old_name='body',
new_name='is_favorited',
),
]
31 changes: 31 additions & 0 deletions authors/apps/articles/migrations/0012_auto_20190123_1537.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 2.1.4 on 2019-01-23 15:37

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('articles', '0011_auto_20190123_0813'),
]

operations = [
migrations.RemoveField(
model_name='favoritearticle',
name='article',
),
migrations.RemoveField(
model_name='favoritearticle',
name='author',
),
migrations.AddField(
model_name='article',
name='favorite',
field=models.ManyToManyField(blank=True, related_name='favorite', to=settings.AUTH_USER_MODEL),
),
migrations.DeleteModel(
name='FavoriteArticle',
),
]
19 changes: 19 additions & 0 deletions authors/apps/articles/migrations/0013_auto_20190123_1545.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 2.1.4 on 2019-01-23 15:45

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('articles', '0012_auto_20190123_1537'),
]

operations = [
migrations.AlterField(
model_name='article',
name='favorite',
field=models.ManyToManyField(default=False, related_name='favorite', to=settings.AUTH_USER_MODEL),
),
]
14 changes: 14 additions & 0 deletions authors/apps/articles/migrations/0014_merge_20190128_0757.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 2.1.5 on 2019-01-28 07:57

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('articles', '0012_merge_20190125_1317'),
('articles', '0013_auto_20190123_1545'),
]

operations = [
]
14 changes: 14 additions & 0 deletions authors/apps/articles/migrations/0015_merge_20190128_0914.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 2.1.5 on 2019-01-28 09:14

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('articles', '0013_merge_20190125_1538'),
('articles', '0014_merge_20190128_0757'),
]

operations = [
]
1 change: 1 addition & 0 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Article(models.Model):
slug = models.SlugField(max_length=50, blank=False, unique=True)
is_deleted = models.BooleanField(default=False)
is_published = models.BooleanField(default=False)
favorite = models.ManyToManyField(User, related_name='favorite', default=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
tagList = TaggableManager()
user_id_likes = models.ManyToManyField(
Expand Down
8 changes: 6 additions & 2 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class ArticleSerializer(TaggitSerializer, serializers.ModelSerializer):
user_id_dislikes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
likes_count = serializers.SerializerMethodField()
dislikes_count = serializers.SerializerMethodField()
# Field to favourite an article
favorite = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

class Meta:
model = Article
Expand All @@ -34,7 +36,8 @@ class Meta:
'user_id_likes',
'user_id_dislikes',
'likes_count',
'dislikes_count']
'dislikes_count',
'favorite']
read_only_fields = ['created',
'modified',
'author',
Expand Down Expand Up @@ -71,7 +74,8 @@ class Meta:
'images',
'author',
'slug',
'tagList']
'tagList',
'favorite']
read_only_fields = ['modified',
'author',
'slug']
Expand Down
110 changes: 75 additions & 35 deletions authors/apps/articles/tests/test_create_article.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ def setUp(self):
self.login_url = reverse('authentication:auth-login')
self.signup_url = reverse('authentication:auth-register')
self.article_listcreate = reverse('articles:articles-listcreate')
self.article_favorite = reverse('articles:articles-favorite',
kwargs={'slug': 'a-new-story'})
self.signup_data = {
"user": {
"username": "kennyg",
Expand Down Expand Up @@ -56,20 +58,20 @@ def signup_user_two(self):
format='json')
token = register.data['token']
return token

def create_article(self, article, token):
del article['images']
response = self.client.post(self.article_listcreate,
article,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
return response

def test_fetch_all_articles(self):
"""Tests to fetch all articles"""
token = self.signup_user_one()
del self.create_article_data['images']
self.client.post(self.article_listcreate,
self.create_article_data,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
del self.create_article_data2['images']
self.client.post(self.article_listcreate,
self.create_article_data2,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.create_article(self.create_article_data, token)
self.create_article(self.create_article_data2, token)
response = self.client.get(self.article_listcreate, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(self.create_article_data['title'],
Expand Down Expand Up @@ -108,11 +110,7 @@ def test_add_articles(self):
def test_get_single_article(self):
"""Test to get a single article"""
token = self.signup_user_one()
del self.create_article_data['images']
self.client.post(self.article_listcreate,
self.create_article_data,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.create_article(self.create_article_data, token)
response = self.client.get(reverse('articles:articles-retrieveupdate',
kwargs={'slug': 'a-new-story'}),
format='json')
Expand All @@ -129,11 +127,7 @@ def test_get_single_article(self):
def test_unauthorized_article_update(self):
"""Test to update an article created by another user"""
token = self.signup_user_one()
del self.create_article_data['images']
self.client.post(self.article_listcreate,
self.create_article_data,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.create_article(self.create_article_data, token)
token2 = self.signup_user_two()
response = self.client.put(reverse('articles:articles-retrieveupdate',
kwargs={'slug': 'a-new-story'}),
Expand All @@ -145,11 +139,7 @@ def test_unauthorized_article_update(self):
def test_authorized_article_update(self):
"""Test to legitimately update an article created by a user"""
token = self.signup_user_one()
del self.create_article_data['images']
self.client.post(self.article_listcreate,
self.create_article_data,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.create_article(self.create_article_data, token)
del self.create_article_data2['images']
response = self.client.put(reverse('articles:articles-retrieveupdate',
kwargs={'slug': 'a-new-story'}),
Expand All @@ -167,11 +157,7 @@ def test_authorized_article_update(self):
def test_to_delete_article(self):
"""Test to delete an article"""
token = self.signup_user_one()
del self.create_article_data['images']
self.client.post(self.article_listcreate,
self.create_article_data,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.create_article(self.create_article_data, token)
response = self.client.put(reverse('articles:articles-delete',
kwargs={'slug': 'a-new-story'}),
self.delete_article,
Expand All @@ -184,11 +170,7 @@ def test_to_delete_article(self):
def test_unauthorized_delete_article(self):
"""Test to delete someone else's article"""
token = self.signup_user_one()
del self.create_article_data['images']
self.client.post(self.article_listcreate,
self.create_article_data,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.create_article(self.create_article_data, token)
token2 = self.signup_user_two()
response = self.client.put(reverse('articles:articles-delete',
kwargs={'slug': 'a-new-story'}),
Expand All @@ -206,3 +188,61 @@ def test_to_fetch_non_exisiting_article(self):
format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual('Not found.', response.data['detail'])

def test_favorite_article(self):
"""Test to favorite an article"""
token = self.signup_user_one()
self.create_article(self.create_article_data, token)
response = self.client.post(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['favorite'], True)

def test_unfavorite_a_favorited_article(self):
"""Test to unfavorite an article that had previously been favorited"""
token = self.signup_user_one()
self.create_article(self.create_article_data, token)
response = self.client.post(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['favorite'], True)
response = self.client.delete(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['favorite'], False)

def test_to_favorite_a_favorited_article(self):
"""Test to favorite a favorited article"""
token = self.signup_user_one()
self.create_article(self.create_article_data, token)
response = self.client.post(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['favorite'], True)
response = self.client.post(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Article already favorited.')

def test_to_unfavorite_a_unfavorited_article(self):
"""Test to unfavorite an unfavorited article"""
token = self.signup_user_one()
self.create_article(self.create_article_data, token)
self.client.post(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
response = self.client.delete(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['favorite'], False)
response = self.client.delete(self.article_favorite,
format='json',
HTTP_AUTHORIZATION='token {}'.format(token))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['message'], 'Article already unfavorited.')
12 changes: 8 additions & 4 deletions authors/apps/articles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
from .views import (ArticleAPIView, ArticleDetailsView,
DeleteArticle, LikeArticleApiView,
DislikeArticleApiView, PostRatingsAPIView,
AverageRatingsAPIView
AverageRatingsAPIView, FavoriteArticle
)


app_name = "articles"
urlpatterns = [path('articles/', ArticleAPIView.as_view(), name="articles-listcreate"),
urlpatterns = [
path('articles/', ArticleAPIView.as_view(), name="articles-listcreate"),
path('articles/<slug:slug>/',
ArticleDetailsView.as_view(),
name="articles-retrieveupdate"),
path('articles/delete/<slug:slug>/',
path('articles/delete/<slug>/',
DeleteArticle.as_view(),
name="articles-delete"),
path('articles/<slug>/like/',
Expand All @@ -24,5 +25,8 @@
name="rate_article"),
path('articles/rate/<slug>/',
AverageRatingsAPIView.as_view(),
name="articles_view_ratings")
name="articles_view_ratings"),
path('articles/<slug>/favorite',
FavoriteArticle.as_view(),
name="articles-favorite")
]
Loading

0 comments on commit e7199d9

Please sign in to comment.