Fakultas Ilmu Komputer UI
Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
PMPL
Collection of Practice
2019
1606875806-practice
Commits
b2521ab1
Commit
b2521ab1
authored
Dec 24, 2019
by
Izzan Fakhril Islam
Browse files
Take Home final exam
parent
d6e6b381
Changes
16
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
b2521ab1
...
...
@@ -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
1606875806_IzzanFakhrilIslam_B.txt
0 → 100644
View file @
b2521ab1
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
README.md
View file @
b2521ab1
...
...
@@ -2,6 +2,8 @@
#### **Izzan Fakhril Islam (1606875806)**
[

](https://gitlab.cs.ui.ac.id/pmpl/practice-collection/2019/1606875806-practice/commits/takehome-final-exam)
[

](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*
.
...
...
tutorial/settings.py
View file @
b2521ab1
...
...
@@ -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
...
...
tutorial_1/unit_tests.py
View file @
b2521ab1
...
...
@@ -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'
)
tutorial_7/functional_tests/test_login.py
View file @
b2521ab1
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
)
tutorial_7/templates/layout/base.html
→
tutorial_7/templates/layout/base
_tutorial_7
.html
View file @
b2521ab1
...
...
@@ -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>
...
...
tutorial_7/templates/partials/footer.html
→
tutorial_7/templates/partials/footer
_tutorial_7
.html
View file @
b2521ab1
File moved
tutorial_7/templates/partials/header.html
→
tutorial_7/templates/partials/header
_tutorial_7
.html
View file @
b2521ab1
...
...
@@ -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>
tutorial_7/templates/tutorial_7.html
View file @
b2521ab1
{% 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>
...
...
tutorial_7/tests.py
deleted
100644 → 0
View file @
d6e6b381
from
django.test
import
TestCase
# Create your tests here.
tutorial_7/unit_tests/__init__.py
0 → 100644
View file @
b2521ab1
tutorial_7/unit_tests/test_app.py
0 → 100644
View file @
b2521ab1
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"
)
tutorial_7/
f
un
ctional
_tests/test_models.py
→
tutorial_7/un
it
_tests/test_models.py
View file @
b2521ab1
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
)
tutorial_7/urls.py
View file @
b2521ab1
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'
),
]
tutorial_7/views.py
View file @
b2521ab1
...
...
@@ -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
())
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment