Fakultas Ilmu Komputer UI

Commit ceee493a authored by Izzan Fakhril Islam's avatar Izzan Fakhril Islam

Merge branch 'takehome-final-exam' into 'master'

Take Home final exam

See merge request !14
parents d6e6b381 b2521ab1
Pipeline #28561 passed with stages
in 13 minutes and 44 seconds
......@@ -74,3 +74,5 @@ FunctionalTest:
- python manage.py test tutorial_5.functional_tests
- python manage.py test tutorial_7.functional_tests
- python manage.py test -p "functional_test*.py"
- coverage run --include='tutorial_7/*' manage.py test tutorial_7
- coverage report -m
URL Gitlab = https://gitlab.cs.ui.ac.id/pmpl/practice-collection/2019/1606875806-practice
Branch penyimpanan hasil implementasi = https://gitlab.cs.ui.ac.id/pmpl/practice-collection/2019/1606875806-practice/tree/takehome-final-exam
......@@ -2,6 +2,8 @@
#### **Izzan Fakhril Islam (1606875806)**
[![coverage report](https://gitlab.cs.ui.ac.id/pmpl/practice-collection/2019/1606875806-practice/badges/takehome-final-exam/coverage.svg)](https://gitlab.cs.ui.ac.id/pmpl/practice-collection/2019/1606875806-practice/commits/takehome-final-exam) [![pipeline status](https://gitlab.cs.ui.ac.id/pmpl/practice-collection/2019/1606875806-practice/badges/takehome-final-exam/pipeline.svg)](https://gitlab.cs.ui.ac.id/pmpl/practice-collection/2019/1606875806-practice/commits/takehome-final-exam)
**Daftar Tutorial:**
1. Tutorial 1: Web Page Pribadi berbasis *Python* dengan *Unit test*.
......
......@@ -97,6 +97,7 @@ if PRODUCTION:
DATABASE_URL = os.environ['DATABASE_URL']
conn = psycopg2.connect(DATABASE_URL, sslmode='require')
DATABASES['default'] = dj_database_url.config(conn_max_age=800, ssl_require=True)
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
elif GITLAB_ENV:
DATABASES = {
'default': {
......@@ -111,7 +112,7 @@ elif GITLAB_ENV:
}
}
}
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD")
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
else:
DATABASES = {
'default': {
......@@ -126,7 +127,7 @@ else:
}
}
}
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD")
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
......@@ -146,9 +147,10 @@ AUTH_PASSWORD_VALIDATORS = [
},
]
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'rvd.cena@gmail.com'
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD")
EMAIL_PORT = 587
EMAIL_USE_TLS = True
......
......@@ -29,3 +29,7 @@ class Tutorial1UnitTest(TestCase):
self.assertEqual(0, calculate_age(date.today().year))
self.assertEqual(19, calculate_age(2000))
self.assertEqual(29, calculate_age(1990))
def test_html_file_used(self):
response = Client().get('/tutorial-1/')
self.assertTemplateUsed(response, 'index_tutorial1.html')
from django.core import mail
from selenium.webdriver.common.keys import Keys
import re
from unittest import skip
from .base import FunctionalTest
......@@ -10,40 +11,40 @@ SUBJECT = 'Your Login Link for Tutorial 7 PMPL'
class LoginTest(FunctionalTest):
def test_can_get_email_link_to_log_in(self):
selenium_host = self.get_host_from_selenium(self.host)
def test_can_get_email_link_to_log_in(context):
selenium_host = context.get_host_from_selenium(context.host)
email_form = selenium_host.find_element_by_name('email')
email_form.send_keys(TEST_EMAIL)
email_form.send_keys(Keys.ENTER)
# A message appears telling her an email has been sent
self.wait_for(lambda: self.assertIn(
context.wait_for(lambda: context.assertIn(
"Check your email, you'll find a message with a link that will log you into the site.",
selenium_host.find_element_by_tag_name('body').text
))
# She checks her email and finds a message
email = mail.outbox[0]
self.assertIn(TEST_EMAIL, email.to)
self.assertEqual(email.subject, SUBJECT)
context.assertIn(TEST_EMAIL, email.to)
context.assertEqual(SUBJECT, email.subject)
# It has a url link in it
self.assertIn('Use this link to log in', email.body)
context.assertIn('Use this link to log in', email.body)
url_search = re.search(r'http://.+/.+$', email.body)
if not url_search:
self.fail(f'Could not find url in email body:\n{email.body}')
context.fail(f'Could not find url in email body:\n{email.body}')
url = url_search.group(0)
self.assertIn(self.host, url)
context.assertIn(context.host, url)
# she clicks it
logged_in_account = self.get_host_from_selenium(url)
logged_in_account = context.get_host_from_selenium(url)
# she is logged in!
self.wait_for(
context.wait_for(
lambda: logged_in_account.find_element_by_link_text('Log out')
)
self.assertIn(TEST_EMAIL, selenium_host.find_element_by_tag_name('body').text)
context.assertIn(TEST_EMAIL, selenium_host.find_element_by_tag_name('body').text)
self.wait_to_be_logged_in(email=TEST_EMAIL)
self.selenium.find_element_by_link_text('Log out').click()
self.wait_to_be_logged_out(email=TEST_EMAIL)
context.wait_to_be_logged_in(email=TEST_EMAIL)
context.selenium.find_element_by_link_text('Log out').click()
context.wait_to_be_logged_out(email=TEST_EMAIL)
......@@ -24,7 +24,7 @@
</style>
<body style="background-color: darkseagreen">
<header class="header-up">
{% include "tutorial_7/../partials/header.html" %}
{% include "tutorial_7/../partials/header_tutorial_7.html" %}
</header>
<content>
<div class="container">
......@@ -37,7 +37,7 @@
<footer class="footer-down">
<!-- TODO Block Footer dan include footer.html -->
{% block footer %}
{% include "tutorial_7/../partials/footer.html" %}
{% include "tutorial_7/../partials/footer_tutorial_7.html" %}
{% endblock %}
</footer>
......
......@@ -17,7 +17,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{% url 'tutorial-7:index' %}" style="color: black">Tutorial 7 PMPL Hehe</a>
<a class="navbar-brand" href="{% url 'tutorial-7:index' %}" style="color: black">Tutorial 7 PMPL by {{ author }}</a>
</div>
</div>
</nav>
{% extends "tutorial_7/../layout/base.html" %}
{% extends "tutorial_7/../layout/base_tutorial_7.html" %}
{% block content %}
<style>
......@@ -52,11 +52,13 @@
<tr>
<th><h5><b>Date/Time</b></h5></th>
<th><h5><b>Todo</b></h5></th>
<th><h5><b>Action</b></h5></th>
</tr>
{% for todos in todos_dict %}
<tr>
<td>{{ todos.date }}</td>
<td>{{ todos.todo_list }}</td>
<td><button class="btn-danger"><a id="id_logout" style="color: white" href="{% url 'tutorial-7:delete_todo' todos.id %}">Delete</a></button></td>
</tr>
{% endfor %}
</table>
......@@ -67,11 +69,13 @@
<tr>
<th><h5><b>Date</b></h5></th>
<th><h5><b>Comment</b></h5></th>
<th><h5><b>Action</b></h5></th>
</tr>
{% for commentary in todos_commentary_dict %}
<tr>
<td>{{ commentary.date }}</td>
<td>{{ commentary.comment }}</td>
<td><button class="btn-danger"><a id="id_logout" style="color: white" href="{% url 'tutorial-7:delete_todo_commentary' commentary.id %}">Delete</a></button></td>
</tr>
{% endfor %}
</table>
......
from django.test import TestCase
# Create your tests here.
from django.http import HttpRequest
from django.test import TestCase
from django.test import Client
from django.urls import resolve
from tutorial_7.views import *
class Tutorial7AppUnitTest(TestCase):
def test_url_is_exist(self):
response_main_page = Client().get('/tutorial-7/')
self.assertEqual(response_main_page.status_code, 200)
def test_using_index_func(self):
found = resolve('/tutorial-7/')
self.assertEqual(found.func, index)
def test_author_name_availability(self):
author_name = "Izzan Fakhril Islam"
response_author = Client().get('/tutorial-7/')
html_response = response_author.content.decode('utf8')
self.assertIn(author_name, html_response)
def test_create_todo_redirect_response(self):
response_create_todo = Client().post(
'/tutorial-7/add_todo/',
{
'date': '2019-12-12T05:44',
'activity': 'test'
}
)
self.assertEqual(response_create_todo.status_code, 302)
def test_create_todo_failed_rendered_response(self):
response_create_todo = Client().post(
'/tutorial-7/add_todo/',
{
'date': '2019-121231',
'activity': 'test'
}
)
self.assertEqual(response_create_todo.status_code, 200)
def test_create_todo_commentary_redirect_response(self):
response_create_todo_commentary = Client().post(
'/tutorial-7/add_todo_commentary/',
{
'date': '2019-12-12',
'comment': 'test commentary',
}
)
self.assertEqual(response_create_todo_commentary.status_code, 302)
def test_create_todo_commentary_failed_rendered_response(self):
response_create_todo_commentary = Client().post(
'/tutorial-7/add_todo_commentary/',
{
'date': '2019-12-121231-123',
'comment': 'test commentary',
}
)
self.assertEqual(response_create_todo_commentary.status_code, 200)
def test_delete_todo_redirect_response(self):
Client().post(
'/tutorial-7/add_todo/',
{
'date': '2019-12-12T05:44',
'activity': 'test'
}
)
delete_response = Client().get('/tutorial-7/1/delete_todo/')
self.assertEqual(delete_response.status_code, 302)
def test_delete_todo_commentary_redirect_response(self):
Client().post(
'/tutorial-7/add_todo_commentary/',
{
'date': '2019-12-12T05:44',
'activity': 'test commentary',
}
)
delete_response = Client().get('/tutorial-7/1/delete_todo_commentary/')
self.assertEqual(delete_response.status_code, 302)
def test_get_comment_by_count(self):
self.assertEqual(get_comment(5), "oh tidak")
self.assertEqual(get_comment(3), "sibuk tapi santai")
self.assertEqual(get_comment(0), "yey, waktunya berlibur")
from django.test import TestCase
from django.contrib.auth import get_user_model
from tutorial_7.models import Token
from datetime import datetime
from tutorial_7.models import Token, TodoList, TodoListCommentary
User = get_user_model()
......@@ -22,3 +23,20 @@ class TokenModelTest(TestCase):
token1 = Token.objects.create(email='a@b.com')
token2 = Token.objects.create(email='a@b.com')
self.assertNotEqual(token1.uid, token2.uid)
class TodoListAndCommentaryModelTest(TestCase):
def test_todo_list_model_is_created(self):
TodoList.objects.create(
todo_list='Hello!',
date=datetime.strptime('2019-12-12T15:15', '%Y-%m-%dT%H:%M')
)
self.assertEqual(TodoList.objects.count(), 51)
def test_todo_list_commentary_model_is_created(self):
TodoListCommentary.objects.create(
comment='Comment',
date=datetime.strptime('2019-12-12', '%Y-%m-%d')
)
self.assertEqual(TodoListCommentary.objects.count(), 51)
from django.conf.urls import url
from .views import index, login, logout, add_todo, add_todo_commentary, send_login_email
from .views import index, login, logout, add_todo, add_todo_commentary, send_login_email, delete_todo, delete_todo_commentary
urlpatterns = [
url(r'^$', index, name='index'),
......@@ -7,6 +7,7 @@ urlpatterns = [
url(r'add_todo_commentary/$', add_todo_commentary, name='add_todo_commentary'),
url(r'^send_email$', send_login_email, name='send_login_email'),
url(r'^login$', login, name='login'),
url(r'^logout$', logout, name='logout')
url(r'^logout$', logout, name='logout'),
url(r'^(?P<id>[0-9]+)/delete_todo/$', delete_todo, name='delete_todo'),
url(r'^(?P<id>[0-9]+)/delete_todo_commentary/$', delete_todo_commentary, name='delete_todo_commentary'),
]
......@@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError
from django.contrib.auth import authenticate
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
from django.shortcuts import get_object_or_404
from django.shortcuts import render, redirect
from .models import TodoList, TodoListCommentary, Token
from datetime import datetime
......@@ -38,6 +39,7 @@ def login(request):
user = auth.authenticate(uid=uid)
if user is not None:
auth.login(request, user)
return redirect('/tutorial-7/')
......@@ -69,6 +71,12 @@ def add_todo(request):
return render(request, HTML_FILE, response)
def delete_todo(request, id=None):
todo_object = get_object_or_404(TodoList, pk=id)
todo_object.delete()
return redirect('/tutorial-7/')
def add_todo_commentary(request):
if request.method == 'POST':
try:
......@@ -87,6 +95,12 @@ def add_todo_commentary(request):
return render(request, HTML_FILE, response)
def delete_todo_commentary(request, id=None):
todo_commentary_object = get_object_or_404(TodoListCommentary, pk=id)
todo_commentary_object.delete()
return redirect('/tutorial-7/')
def send_login_email(request):
email = request.POST['email']
uid = str(uuid.uuid4())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment