Due: 11/2 (Fri) 20:59 (This is a hard deadline)
You need to implement unit tests for your Angular project you already submitted in homework 2.
This was a part of homework 2 but postponed due to the course schedule.
Therefore, you must not modify your project features (in *.ts
files except *.spec.ts
) but just update (or add) the *.spec.ts
files to make all *.ts
files under your src/app
directory should have corresponding *.spec.ts
files that performs unit tests on your code.
All pages/components should have proper unit tests to test its functionalities, written in Jasmine, run by Karma (as shown in this link and the practice session). Your tests are expected to cover all of your code, and we will give credits according to your coverage results. You can see the coverage information of your application as shown here. Also, all of your tests must pass.
In this assignment you will implement a backend service for the blog frontend that you have created in homework 2. This is an individual assignment.
Through this assignment, you are expected to:
- Build a RESTful API server with Django (2.1.2)
- Understand how communication between the client and the server occurs
- Test your Django application
Our myblog
project consists of a single app, blog
.
Because we provide the url routing and setting of the project already, you are expected to update the blog
app mainly.
As you have seen in homework 2, our blog has three models: User, Article, and Comment.
- Each user should be able to sign up, sign in and sign out.
- Only those users who are signed in are allowed to read or write articles and comments.
- Users should be able to update or delete articles and comments only which they have created.
For the user model, you must use the Django default user model and the django authentication system to manage user authentication. In homework 2, we didn't cover the real user authentication process. Now with a proper backend, we can manage user sessions and authentication supported by Django.
For articles, you need to create a model named as Article
that consists of following fields:
Field name | Type |
---|---|
title |
Char Field |
content |
Text Field |
author |
Foreign Key |
The author must be a (foreign) key referring a User.
For comments, you need to create a model named as Comment
that consists of following fields:
Field name | Type |
---|---|
article |
Foreign Key |
content |
Text Field |
author |
Foreign Key |
The article and author must be a (foreign) key referring an Article and a User.
To check whether you implemented your model correctly or not, please check the following code works well with your model implementation (in your test code or somewhere else).
from .models import Article, Comment
from django.contrib.auth.models import User
new_user = User.objects.create_user(username='swpp', password='iluvswpp') # Django default user model
new_article = Article(title='I Love SWPP!', content='Believe it or not', author=new_user)
new_article.save()
new_comment = Comment(article=new_article, content='Comment!', author=new_user)
new_comment.save()
Detailed specifications of RESTful APIs are as following:
API | GET | POST | PUT | DELETE |
---|---|---|---|---|
api/signup |
X | Create new user | X | X |
api/signin |
X | Log in | X | X |
api/signout |
Log out | X | X | X |
api/article |
Get article list | Create new article | X | X |
api/article/:article_id |
Get specified article | X | Edit specified article | Delete specified article |
api/article/:article_id/comment |
Get comments of specified article | Create comment on specified article | X | X |
api/comment/:comment_id |
Get specified comment | X | Edit specified comment | Delete specified comment |
Note that the APIs are slightly different from that of homework 2. Since we have used mock-backend, APIs were limited in homework 2. In this assignment, we will implement a more RESTful API.
POST and PUT requests should contain data using the JSON format in the body of the request. For each model, the JSON format should look like:
- User :
{username: string, password: string}
- Article :
{title: string, content: string}
- Comment :
{content: string}
Also, the user information will be included in the request
automatically. Check request.user
.
For each API you should respond with the appropriate HTTP response code. The list of response codes you should use is as follows:
200
(Ok) : Request was responded successfully.201
(Created) : Request has created new resources successfully.204
(No Content) : Request was responded successfully but without any content.401
(Unauthorized) : Request requires authentication. This should be returned if you are requesting without signing in.403
(Forbidden) : Request is forbidden. This should be returned if your request tries to modify resources of which you are not the owner.404
(Not Found) : Requested resource is not found.405
(Method not allowed) : Requested URL does not allow the method of the request.
Please make sure to implement your request methods under the following global specifications:
- For all non-allowed requests (X marked in the API table), response with
405
. - For all requests about article and comment without signing in, response with
401
(and any information must not be modified). - For all requests about non-existing article and comment, response with
404
(and any information must not be modified). - For all PUT and DELETE requests from non-author, response with
403
(and any information must not be modified).
Among these global specifications, the prior specification has the higher priority. For example, if someone requests for a non-existing article without signing in, response with 401
instead of 404
.
Also, please make sure to implement your request methods under the following detailed specifications (in your views.py
)
- POST
api/signup
Create a user with the information given by request JSON body and response with201
- POST
api/signin
Authenticate with the information given by request JSON body. If success, log-in (the authentication info should be changed properly) and response with204
. If fail, response with401
. - GET
api/signout
If the user is authenticated, log-out (the authentication info should be changed properly) and response with204
. If not, response with401
. - GET
api/article
Response with a JSON having a list of dictionaries for each article'stitle
,content
, andauthor
. The value of theauthor
must be theid
of the author but not herusername
. - POST
api/article
Create an article with the information given by request JSON body and response with201
- GET
api/article/:article_id
Response with a JSON having a dictionary for the target article'stitle
,content
, andauthor
. The value of theauthor
must be theid
of the author but not herusername
. - PUT
api/article/:article_id
Update the target article with the information given by request JSON body and response with200
- DELETE
api/article/:article_id
Delete the target article and response with200
. When deleting an article, all comments under the target article (but not any comments under other articles, of course) must be deleted also. - GET
api/article/:article_id/comment
Response with a JSON having a list of dictionaries for each comment'sarticle
,content
, andauthor
. The value of thearticle
and theauthor
must be theid
of the article and the author but not thetitle
and herusername
. - POST
api/article/:article_id/comment
Create a comment with the information given by request JSON body and response with201
. - GET
api/comment/:comment_id
Response with a JSON having a dictionary for the target comment'sarticle
,content
, andauthor
. The value of thearticle
and theauthor
must be theid
of the article and the author but not thetitle
and herusername
. - PUT
api/comment/:comment_id
Update the target comment with the information given by request JSON body and response with200
- DELETE
api/comment/:comment_id
Delete the target comment and response with200
. When deleting a comment, other users, articles and comments must not be deleted also.
You should also write tests to verify that your blog backend is implemented correctly. Your tests should reach 100% of both the statement coverage and the branch coverage.
You can run your test code with coverage check by:
- Install :
pip install coverage
- Statement coverage :
coverage run --source='./blog' manage.py test
- Branch coverage :
coverage run --branch --source='./blog' manage.py test
After this, you can check your coverage report by:
coverage report
In Django, it is rather complex to send request other than GET method with RESTful API due to the CSRF token. To successfully handle such requests, try the following steps:
- Before sending the request, send GET request to
/api/token
. The response will come with an empty content and will set the cookiecsrftoken
in your browser. - Send the POST request with a header containing
HTTP_X_CSRFTOKEN
as the value of thecsrftoken
.
For more detail, see test_csrf
of the blog/tests.py
file in the skeleton code.
You may change this part if you have a better way of handling the CSRF token, but disabling the protection itself is NOT permitted.
To test your APIs, we recommend using ARC (Advanced REST Client). Check arc.pdf
for detailed information.
This assignment is composed of a total of 85 points (15 points for Angular testing and 70 points for Django). We will test your Django code under Python 3.6.
- Angular Testing (15 points)
- User APIs (15 points)
- Article APIs (20 points)
- Comment APIs (20 points)
- Django Testing (15 points)
Like HW 2, if some basic features are not implemented properly, many other test cases can fail. For example, if the signing-in process works badly, most of the cases above will fail. We'll try to give some partial points in this case, but it might not be enough.
Due: 11/2 (Fri) 20:59 (This is a hard deadline)
We will check the snapshot of the master branch of your Github repository at the deadline and grade it.
Please name your repository as swpp-hw3-YOUR_USERNAME
, and replace YOUR_USERNAME with you own GitHub username.
Refer to HW1 to create another private repository. (Make sure to push your work on Github on time and add sanha
, yuyupopo
, and skystar-p
as a collaborator in your repository settings.)
Also, make sure to push your work on Github on time.
You won't need to send us an email for submission, but we will pull each repositories at the time specified.
Please put your angular projects and django projects in the root folder (not inside another hw3
or skeleton
folder) appropriately.
Your directory hierarchy should look like this:
repository_root/
angular/
README.md
e2e/
...
src/
app/
assets/
environment/
...
package.json
...
django/
README.md (this file)
blog/
...
myblog/
...
manage.py
...