-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
273 additions
and
15 deletions.
There are no files selected for viewing
18 changes: 18 additions & 0 deletions
18
authors/apps/articles/migrations/0004_auto_20181016_1206.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by Django 2.1.1 on 2018-10-16 09:06 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('articles', '0003_auto_20181016_1048'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='category', | ||
name='title', | ||
field=models.CharField(default='general', max_length=100), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
authors/apps/profiles/migrations/0002_profile_favorites.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Generated by Django 2.1.1 on 2018-10-16 09:06 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('articles', '0004_auto_20181016_1206'), | ||
('profiles', '0001_initial'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='profile', | ||
name='favorites', | ||
field=models.ManyToManyField(related_name='favorited_by', to='articles.Article'), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,43 @@ | ||
from rest_framework import serializers | ||
from .models import Profile, FollowingUser | ||
from authors.apps.articles.models import Article | ||
|
||
|
||
class ProfileSerializer(serializers.ModelSerializer): | ||
username = serializers.CharField(source='user.username') | ||
first_name = serializers.CharField(allow_blank=True, required=False) | ||
last_name = serializers.CharField(allow_blank=True, required=False) | ||
bio = serializers.CharField(allow_blank=True, required=False) | ||
|
||
|
||
class Meta: | ||
model = Profile | ||
fields = ('username', 'first_name','last_name','bio','image','following','number_of_articles','created_at','updated_at') | ||
fields = ('username', 'first_name', 'last_name', 'bio', 'image', | ||
'following', 'number_of_articles', 'created_at', 'updated_at') | ||
read_only_fields = ('username',) | ||
|
||
|
||
class ProfilesSerializers(serializers.ModelSerializer): | ||
username = serializers.CharField(source='user.username') | ||
first_name = serializers.CharField(allow_blank=True, required=False) | ||
last_name = serializers.CharField(allow_blank=True, required=False) | ||
bio = serializers.CharField(allow_blank=True, required=False) | ||
following = serializers.BooleanField() | ||
|
||
favorites = serializers.SerializerMethodField() | ||
|
||
class Meta: | ||
model = Profile | ||
fields = ('username', 'first_name','last_name','bio', 'following','image') | ||
fields = ('username', 'first_name', 'last_name', 'bio', 'following', 'image', | ||
'following', 'number_of_articles', 'created_at', 'updated_at', 'favorites') | ||
read_only_fields = ('username',) | ||
|
||
class FollowerSerializer(serializers.ModelSerializer): | ||
def get_favorites(self, instance): | ||
request = self.context.get('request', None) | ||
favorites = instance.favorites.through.objects.filter(profile__user=instance.user) | ||
|
||
return [Article.objects.get(pk=favorite.article_id).slug for favorite in favorites] | ||
|
||
class FollowerSerializer(serializers.ModelSerializer): | ||
|
||
class Meta: | ||
model = FollowingUser | ||
fields = ('following_user','followed_user','date_added') | ||
|
||
fields = ('following_user','followed_user','date_added') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
from rest_framework.test import APIClient, APITestCase | ||
from rest_framework import status | ||
from ..test_authentication.test_base import BaseTest | ||
from authors.apps.articles.models import Article | ||
from authors.apps.authentication.models import User | ||
from authors.apps.profiles.models import Profile | ||
|
||
class FavoriteArticleTest(APITestCase, BaseTest): | ||
def setUp(self): | ||
BaseTest.__init__(self) | ||
self.client = APIClient() | ||
self.password = 'Ckato12345!' | ||
self.login_data = {"user": { | ||
"username": "ckato1", | ||
"email": "ckato1@gmail.com", | ||
"password": "Ckato12345!" | ||
}} | ||
self.login_data2 = {"user": { | ||
"username": "ckato2", | ||
"email": "ckato2@gmail.com", | ||
"password": "Ckato12345!" | ||
}} | ||
# create first user | ||
self.user1 = User.objects.create_user( | ||
'ckato1', 'ckato1@gmail.com', password=self.password) | ||
# activate account | ||
self.user1.is_active = True | ||
self.user1.is_verified = True | ||
self.user1.save() | ||
self.login_response1 = self.client.post( | ||
"/api/users/login/", self.login_data, format='json') | ||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.article1 = self.client.post('/api/articles/',self.create_article, | ||
format="json") | ||
self.assertEqual(self.article1.status_code, status.HTTP_201_CREATED) | ||
# create second user | ||
self.user2 = User.objects.create_user( | ||
'ckato2', 'ckato2@gmail.com', password=self.password) | ||
# activate account | ||
self.user2.is_active = True | ||
self.user2.is_verified = True | ||
self.user2.save() | ||
self.login_response2= self.client.post( | ||
"/api/users/login/", self.login_data2, format='json') | ||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response2.data['token'] | ||
) | ||
self.article2 = self.client.post('/api/articles/',self.create_article, | ||
format="json") | ||
self.assertEqual(self.article2.status_code, status.HTTP_201_CREATED) | ||
|
||
def test_favorite_article(self): | ||
|
||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.response = self.client.post('/api/articles/{}/favorite/'.format(self.article2.data["slug"])) | ||
self.assertEqual(self.response.status_code, status.HTTP_201_CREATED) | ||
|
||
def test_favorite_favorited_article(self): | ||
|
||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.client.post('/api/articles/{}/favorite/'.format(self.article2.data["slug"])) | ||
self.response = self.client.post('/api/articles/{}/favorite/'.format(self.article2.data["slug"])) | ||
|
||
self.assertEqual(self.response.status_code, status.HTTP_400_BAD_REQUEST) | ||
|
||
def test_favorite_own_article(self): | ||
|
||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.response = self.client.post('/api/articles/{}/favorite/'.format(self.article1.data["slug"])) | ||
self.assertEqual(self.response.status_code, status.HTTP_400_BAD_REQUEST) | ||
|
||
def test_favorite_non_slug_article(self): | ||
|
||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.response = self.client.post('/api/articles/{}/favorite/'.format('x-x-x')) | ||
self.assertEqual(self.response.status_code, status.HTTP_404_NOT_FOUND) | ||
|
||
def test_unfavorite_article(self): | ||
|
||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.client.post('/api/articles/{}/favorite/'.format(self.article2.data["slug"])) | ||
self.response = self.client.delete('/api/articles/{}/unfavorite/'.format(self.article2.data["slug"])) | ||
self.assertEqual(self.response.status_code, status.HTTP_200_OK) | ||
|
||
def test_unfavorite_unfavorited_article(self): | ||
|
||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.client.post('/api/articles/{}/favorite/'.format(self.article2.data["slug"])) | ||
self.client.delete('/api/articles/{}/unfavorite/'.format(self.article2.data["slug"])) | ||
self.response = self.client.delete('/api/articles/{}/unfavorite/'.format(self.article2.data["slug"])) | ||
self.assertEqual(self.response.status_code, status.HTTP_400_BAD_REQUEST) | ||
|
||
def test_unfavorite_unexistent_article(self): | ||
|
||
self.client.credentials( | ||
HTTP_AUTHORIZATION='Token ' + self.login_response1.data['token'] | ||
) | ||
self.response = self.client.delete('/api/articles/{}/unfavorite/'.format('x-x-x')) | ||
self.assertEqual(self.response.status_code, status.HTTP_404_NOT_FOUND) |