Skip to content

Commit

Permalink
Merge 049bec4 into bf61254
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruiru11 committed Feb 4, 2019
2 parents bf61254 + 049bec4 commit 9419b36
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 10 deletions.
60 changes: 51 additions & 9 deletions authors/apps/articles/tests/test_articles.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from ..models import Article
from ...authentication.models import User
from authors.apps.authentication.messages import read_stats_message


class ArticleTestCase(APITestCase):
Expand All @@ -19,6 +20,7 @@ def setUp(self):
self.all_article_url = reverse("articles:articles")
self.login_url = reverse("auth:login")
self.register = reverse("auth:register")
self.read_stats = reverse("read:user_read_stats")
self.client = APIClient()
self.valid_article_data = {
"article": {
Expand Down Expand Up @@ -77,6 +79,13 @@ def get_slug_from_title(self, title):
)
return specific_article_url

def get_slug(self, title):
"""
Get slug
"""
slug = slugify(title)
return slug

def create_article(self, data):
"""
Create an article
Expand Down Expand Up @@ -117,22 +126,55 @@ def test_get_one_article(self):
)
self.assertEqual(response.status_code, 200)


def test_read_time(self):
def test_get_stat(self):
"""
Test GET /api/v1/article/<slug>/
"""
token = self.login(self.user_data)
self.create_article(self.valid_article_data['article'])
url = self.get_slug_from_title(
self.valid_article_data['article']['title'])
response = self.client.get(
url,
format="json",
HTTP_AUTHORIZATION="Bearer {}".format(token)
)
self.read_stats,
content_type='application/json',
HTTP_AUTHORIZATION="Bearer {}".format(token)
)
self.assertEqual(response.status_code, 200)
self.assertIn(response.data['read_time'],'0:01:00')

def test_read(self):
"""
Test reading an article that doesnot exist
"""
token = self.login(self.user_data)
self.create_article(self.valid_article_data['article'])
slug = "its-a-test-article"
response = self.client.get(
reverse("read:article_read", kwargs={
"slug":slug
}),
content_type='application/json',
HTTP_AUTHORIZATION="Bearer {}".format(token)
)
self.assertEqual(response.status_code, 404)
self.assertIn(response.data['message'],
read_stats_message['read_error'])

def test_read_new(self):
"""
"""
token = self.login(self.user_data)
self.create_article(self.valid_article_data['article'])
slug = self.get_slug(self.valid_article_data['article']['title'])
response = self.client.get(
reverse("read:article_read", kwargs={
"slug":slug
}),
content_type='application/json',
HTTP_AUTHORIZATION="Bearer {}".format(token)
)
self.assertEqual(response.status_code, 404)
self.assertIn(response.data['message'],
read_stats_message['read_error'])


def test_remove_one_article(self):
"""
Expand Down
12 changes: 12 additions & 0 deletions authors/apps/articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from .serializers import ArticleSerializer, TagSerializers
from .messages import error_msgs, success_msg

from authors.apps.reading_stats.models import ReadStats


class ArticleAPIView(generics.ListCreateAPIView):
"""
Expand Down Expand Up @@ -92,6 +94,16 @@ def get(self, request, slug, *args, **kwargs):
raise exceptions.NotFound({
"message": error_msgs['not_found']
})
#this checks if an istance of read exists
#if it doesn't then it creates a new one
if request.user.id:
if not ReadStats.objects.filter(user=request.user, article=article).exists():
user_stat = ReadStats(
user = request.user,
article = article
)
user_stat.save()

serializer = ArticleSerializer(
article,
context={
Expand Down
6 changes: 6 additions & 0 deletions authors/apps/authentication/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,9 @@
'Dislike': "Disliked",
'Null': "Null",
}

read_stats_message = {
"read_status":"Article has been read",
"read_update":"You have already read this article",
"read_error":"Article doesnot exist check details again"
}
Empty file.
3 changes: 3 additions & 0 deletions authors/apps/reading_stats/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
5 changes: 5 additions & 0 deletions authors/apps/reading_stats/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class ReadingStartsConfig(AppConfig):
name = 'reading_starts'
Empty file.
20 changes: 20 additions & 0 deletions authors/apps/reading_stats/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from django.db import models

from authors.apps.authentication.models import User
from authors.apps.articles.models import Article


class ReadStats(models.Model):
"""
The model for user read starts
"""
user = models.ForeignKey(
User, on_delete=models.CASCADE, null=False, blank=False)
article = models.ForeignKey(
Article, on_delete=models.CASCADE, null=False, blank=False)
article_read = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return self.article.title
22 changes: 22 additions & 0 deletions authors/apps/reading_stats/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from rest_framework import serializers

from .models import ReadStats


class ReadStatsSerializers(serializers.ModelSerializer):
""""
Serializer class for our ReadStats model
"""

article = serializers.SerializerMethodField()

class Meta:
model = ReadStats

fields = '__all__'

def get_article(self, stats):
return {
"article": stats.article.title,
"slug": stats.article.slug
}
Empty file.
195 changes: 195 additions & 0 deletions authors/apps/reading_stats/tests/test_read_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
from django.test import TestCase, Client
from django.urls import reverse
from rest_framework import status

from ..models import ReadStats
from authors.apps.articles.models import Article
from django.template.defaultfilters import slugify
from authors.apps.authentication.messages import read_stats_message


class ReadStatsTestCase(TestCase):

def setUp(self):
client = Client()
self.login_url = reverse("auth:login")
self.register_url = reverse("auth:register")
self.read_stats = reverse("read:user_read_stats")
self.all_article_url = reverse("articles:articles")

self.valid_article_data = {
"article": {
"image_path": "",
"title": "Its a test article",
"body": "Its a test article body"
}
}

self.valid_user_credentials = {
"user": {
"username": "Alpha",
"email": "alphaandela@gmail.com",
"password": "@Alpha254"
}
}

self.user_credentials = {
"user": {
"username": "Alpha",
"email": "alphaandela@gmail.com",
"password": "@Alpha254"
}
}

self.valid_article_data = {
"article": {
"image_path": "......",
"title": "Its a test article",
"body": "Its a test article body"
}
}

def user_registration(self, data):
# register a user
response = self.client.post(
self.register_url,
self.valid_user_credentials,
content_type='application/json'
)
return response

def login(self, data):
# login user
response = self.client.post(
self.login_url,
self.valid_user_credentials,
content_type='application/json'
)
return response

def get_slug_from_title(self, title):
"""
Get slug
"""
specific_article_url = reverse(
"articles:specific_article",
kwargs={
"slug": slugify(title)
}
)
return specific_article_url

# def test_create_article(self):
# """
# Create an article
# """
# self.user_registration(self.valid_user_credentials)
# token = self.login(self.valid_user_credentials).data['token']

# response = self.client.post(
# self.all_article_url,
# self.valid_article_data,
# format="json",
# HTTP_AUTHORIZATION="Bearer " + token
# )
# import pdb; pdb.set_trace()
# return response.data

def test_user_read_starts(self):
"""
test to get list of users read articles
"""
self.user_registration(self.valid_user_credentials)
self.login(self.valid_user_credentials)
res = self.login(self.valid_user_credentials)
token = res.data['token']
response = self.client.get(
self.read_stats,
content_type='application/json',
HTTP_AUTHORIZATION='Bearer ' + token
)
self.assertEqual(response.status_code, 200)

def test_user_start(self):
"""
test length of data returned
"""
self.user_registration(self.valid_user_credentials)
self.login(self.valid_user_credentials)
res = self.login(self.valid_user_credentials)
token = res.data['token']
response = self.client.get(
self.read_stats,
content_type='application/json',
HTTP_AUTHORIZATION='Bearer ' + token
)
data = response.data

self.assertTrue(len(data) == 4)

def test_user_results_with_no_read(self):
"""
test length of result data returned
"""
self.user_registration(self.valid_user_credentials)
self.login(self.valid_user_credentials)
res = self.login(self.valid_user_credentials)
token = res.data['token']
response = self.client.get(
self.read_stats,
content_type='application/json',
HTTP_AUTHORIZATION='Bearer ' + token
)
data = response.data
self.assertTrue(len(data['results']) == 0)


def test_user_read_article_that_doesnot_exist(self):
"""
test if a user tires to read a non existent article
"""
self.user_registration(self.valid_user_credentials)
self.login(self.valid_user_credentials)
res = self.login(self.valid_user_credentials)
slug = "slug"
token = res.data['token']
response = self.client.get(
"api/v1/read," + slug + "/",
content_type='application/json',
HTTP_AUTHORIZATION='Bearer ' + token
)
self.assertEqual(response.status_code, 404)

def test_stat_without_being_authenticated(self):
"""
test to ensure authentication is required
"""
self.login(self.valid_user_credentials)
token = "new"
response = self.client.get(
self.read_stats,
content_type='application/json',
HTTP_AUTHORIZATION='Bearer ' + token
)
self.assertEqual(response.status_code, 401)

def test_read_user_response(self):
"""
test to ensure authentication is required
"""
self.user_registration(self.valid_user_credentials)
self.login(self.valid_user_credentials)
res = self.login(self.valid_user_credentials)
slug = "slug"
token = res.data['token']
response = self.client.get(
reverse("read:article_read", kwargs={
"slug":slug
}),
content_type='application/json',
HTTP_AUTHORIZATION="Bearer {}".format(token)
)
self.assertEqual(response.status_code, 404)
self.assertIn(response.data['message'],
read_stats_message['read_error'])

12 changes: 12 additions & 0 deletions authors/apps/reading_stats/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from django.urls import path

from .views import UserReadStatsView, UserCompleteStatView



app_name = "read"

urlpatterns = [
path("read-stats/", UserReadStatsView.as_view(), name="user_read_stats"),
path("read/<str:slug>/", UserCompleteStatView.as_view(), name="article_read"),
]
Loading

0 comments on commit 9419b36

Please sign in to comment.