Fakultas Ilmu Komputer UI

Commit a69f5c90 authored by Jordan Muhammad Andrianda's avatar Jordan Muhammad Andrianda
Browse files

Merge branch 'latihan8b' into 'master'

Latihan8b

See merge request !12
parents a82ce108 bf4cd571
EMAIL_PASSWORD=yoursekritpasswordhere
from accounts.models import User, Token
class PasswordlessAuthenticationBackend(object):
def authenticate(self, uid):
try:
token = Token.objects.get(uid=uid)
......@@ -10,9 +10,10 @@ class PasswordlessAuthenticationBackend(object):
return User.objects.create(email=token.email)
except Token.DoesNotExist:
return None
def get_user(self, email):
try:
return User.objects.get(email=email)
except User.DoesNotExist:
return None
\ No newline at end of file
None
from django.db import models
import uuid
from django.contrib import auth
from django.db import models
auth.signals.user_logged_in.disconnect(auth.models.update_last_login)
class User(models.Model):
......
from django.test import TestCase
from django.contrib import auth
from accounts.models import Token
User = auth.get_user_model()
class UserModelTest(TestCase):
def test_user_is_valid_with_email_only(self):
user = User(email="a@b.com")
user.full_clean() # should not raise
def test_email_is_primary_key(self):
user = User(email="a@b.com")
self.assertEqual(user.pk, "a@b.com")
def test_no_problem_with_auth_login(self):
user = User.objects.create(email="edith@example.com")
user.backend = ""
request = self.client.request().wsgi_request
auth.login(request, user) # should not raise
class TokenModelTest(TestCase):
def test_links_user_with_auto_generated_uid(self):
token1 = Token.objects.create(email="a@b.com")
token2 = Token.objects.create(email="a@b.com")
self.assertNotEqual(token1.uid, token2.uid)
......@@ -44,74 +44,70 @@ class SendLoginEmailViewTest(TestCase):
self.assertEqual(from_email, "noreply@superlists")
self.assertEqual(to_list, ["edith@example.com"])
# def test_adds_success_message(self):
# response = self.client.post('/accounts/send_login_email', data={
# 'email': 'edith@example.com'
# }, follow=True)
# message = list(response.context['messages'])[0]
# self.assertEqual(
# message.message,
# "Check your email, we've sent you a link you can use to log in."
# )
# self.assertEqual(message.tags, "success")
# @patch('accounts.views.messages')
# def test_adds_success_message_with_mocks(self, mock_messages):
# response = self.client.post('/accounts/send_login_email', data={
# 'email': 'edith@example.com'
# })
# expected = "Check your email, we've sent you a link you can use to log in."
# self.assertEqual(
# mock_messages.success.call_args,
# call(response.wsgi_request, expected),
# )
def test_adds_success_message(self):
response = self.client.post(
"/accounts/send_login_email",
data={"email": "edith@example.com"},
follow=True,
)
message = list(response.context["messages"])[0]
self.assertEqual(
message.message,
"Check your email, we've sent you a link you can use to log in.",
)
self.assertEqual(message.tags, "success")
@patch("accounts.views.messages")
def test_adds_success_message_with_mocks(self, mock_messages):
response = self.client.post(
"/accounts/send_login_email", data={"email": "edith@example.com"}
)
expected = "Check your email, we've sent you a link you can use to log in."
self.assertEqual(
mock_messages.success.call_args, call(response.wsgi_request, expected)
)
class LoginViewTest(TestCase):
class LoginViewTest(TestCase):
def test_redirects_to_home_page(self):
response = self.client.get('/accounts/login?token=abcd123')
self.assertRedirects(response, '/')
response = self.client.get("/accounts/login?token=abcd123")
self.assertRedirects(response, "/")
def test_creates_token_associated_with_email(self):
self.client.post('/accounts/send_login_email', data={
'email': 'edith@example.com'
})
self.client.post(
"/accounts/send_login_email", data={"email": "edith@example.com"}
)
token = Token.objects.first()
self.assertEqual(token.email, 'edith@example.com')
self.assertEqual(token.email, "edith@example.com")
@patch('accounts.views.send_mail')
@patch("accounts.views.send_mail")
def test_sends_link_to_login_using_token_uid(self, mock_send_mail):
self.client.post('/accounts/send_login_email', data={
'email': 'edith@example.com'
})
self.client.post(
"/accounts/send_login_email", data={"email": "edith@example.com"}
)
token = Token.objects.first()
expected_url = f'http://testserver/accounts/login?token={token.uid}'
expected_url = f"http://testserver/accounts/login?token={token.uid}"
(subject, body, from_email, to_list), kwargs = mock_send_mail.call_args
self.assertIn(expected_url, body)
@patch('accounts.views.auth')
def test_calls_authenticate_with_uid_from_get_request(self, mock_auth):
self.client.get('/accounts/login?token=abcd123')
self.assertEqual(
mock_auth.authenticate.call_args,
call(uid='abcd123')
)
@patch("accounts.views.auth")
def test_calls_authenticate_with_uid_from_get_request(self, mock_auth):
self.client.get("/accounts/login?token=abcd123")
self.assertEqual(mock_auth.authenticate.call_args, call(uid="abcd123"))
@patch('accounts.views.auth')
@patch("accounts.views.auth")
def test_calls_auth_login_with_user_if_there_is_one(self, mock_auth):
response = self.client.get('/accounts/login?token=abcd123')
response = self.client.get("/accounts/login?token=abcd123")
self.assertEqual(
mock_auth.login.call_args,
call(response.wsgi_request, mock_auth.authenticate.return_value)
mock_auth.login.call_args,
call(response.wsgi_request, mock_auth.authenticate.return_value),
)
@patch('accounts.views.auth')
@patch("accounts.views.auth")
def test_does_not_login_if_user_is_not_authenticated(self, mock_auth):
mock_auth.authenticate.return_value = None
self.client.get('/accounts/login?token=abcd123')
self.assertEqual(mock_auth.login.called, False)
mock_auth.authenticate.return_value = None
self.client.get("/accounts/login?token=abcd123")
self.assertEqual(mock_auth.login.called, False)
from django.conf.urls import url
from accounts import views
from django.contrib.auth import logout
urlpatterns = [
url(r"^send_login_email$", views.send_login_email, name="send_login_email"),
url(r"^login$", views.login, name="login"),
# url(r'^logout$', views.logout, name='logout'),
url(r'^logout$', logout, {'next_page': '/'}, name='logout'),
]
import uuid
# from django.shortcuts import render
# import uuid
import sys
from django.contrib.auth import authenticate
from django.contrib.auth import login as auth_login
# from django.contrib.auth import authenticate
# from django.contrib.auth import login as auth_login
from django.core.mail import send_mail
from django.shortcuts import redirect
from django.contrib import auth, messages
......@@ -12,21 +13,34 @@ from accounts.models import Token
def send_login_email(request):
email = request.POST['email']
token = Token.objects.create(email=email)
url = request.build_absolute_uri(
url = request.build_absolute_uri(
reverse('login') + '?token=' + str(token.uid)
)
message_body = f'Use this link to log in:\n\n{url}'
# print(type(send_mail))
send_mail(
'Your login link for Superlists',
message_body,
'noreply@superlists',
[email]
)
# messages.add_message(
# request,
# messages.SUCCESS,
# "Check your email, we've sent you a link you can use to log in."
# )
messages.success(request,
"Check your email, we've sent you a link you can use to log in."
)
return redirect('/')
def login(request):
user = auth.authenticate(uid=request.GET.get('token'))
if user:
auth.login(request, user)
return redirect('/')
from django.core import mail
from selenium.webdriver.common.keys import Keys
from unittest import skip
import re
from .base import FunctionalTest
TEST_EMAIL = "jerysha99@gmail.com"
TEST_EMAIL = "edith@example.com"
SUBJECT = "Your login link for Superlists"
......@@ -37,10 +38,19 @@ class LoginTest(FunctionalTest):
url = url_search.group(0)
self.assertIn(self.live_server_url, url)
# she clicks it
# she clicks it
self.browser.get(url)
# she is logged in!
self.wait_for(lambda: self.browser.find_element_by_link_text("Log out"))
navbar = self.browser.find_element_by_css_selector(".navbar")
self.assertIn(TEST_EMAIL, navbar.text)
# Now she logs out
self.browser.find_element_by_link_text("Log out").click()
# She is logged out
self.wait_for(lambda: self.browser.find_element_by_name("email"))
navbar = self.browser.find_element_by_css_selector(".navbar")
self.assertNotIn(TEST_EMAIL, navbar.text)
......@@ -7,51 +7,62 @@
</head>
<body>
<div class="container">
<div class="navbar">
{% if user.is_authenticated %}
<p>Logged in as {{ user.email }}</p>
<p><a id="id_logout" href="{% url 'logout' %}">Log out</a></p>
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<a class="navbar-brand" href="/">Superlists</a>
{% if user.email %}
<ul class="nav navbar-nav navbar-right">
<li class="navbar-text">Logged in as {{ user.email }}</li>
<li><a href="#">Log out</a></li>
</ul>
{% else %}
<form class="navbar-form navbar-right"
method="POST"
action="{% url 'send_login_email' %}">
Enter email to log in: <input name="email" type="text" />
<form class="navbar-form navbar-right" method="POST" action="{% url 'send_login_email' %}">
<span>Enter email to log in:</span>
<input class="form-control" name="email" type="text" />
{% csrf_token %}
</form>
{% endif %}
</div>
{% if messages %}
<div class="row">
<div class="col-md-8">
{% for message in messages %}
{% if message.level_tag == 'success' %}
<div class="alert alert-success">{{ message }}</div>
{% else %}
<div class="alert alert-warning">{{ message }}</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="text-center">
<h1>{% block header_text %}{% endblock %}</h1>
<form method="POST" action="{% block form_action %}{% endblock %}">
<input name="item_text" id="id_new_item" class="form-control input-lg"
placeholder="Enter a to-do item"
/>
{% csrf_token %}
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3">
{% block table %}
{% endblock %}
</div>
</div>
</nav>
{% if messages %}
<div class="row">
<div class="col-md-8">
​{% for message in messages %}
{% if message.level_tag == 'success' %}
<div class="alert alert-success">{{ message }}</div>
{% else %}
<div class="alert alert-warning">{{ message }}</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
<div class="row">
<div class="col-md-12 col-md-offset-3">
<div class="text-center">
<h1>{% block header_text %}{% endblock %}</h1>
<form method="POST" action="{% block form_action %}{% endblock %}">
<input name="item_text" id="id_new_item" class="form-control input-lg" placeholder="Enter a to-do item" />
{% csrf_token %}
{% if error %}
<div class="form-group has-error">
<span class="help-block">{{ error }}</span>
</div>
​{% endif %}
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-md-offset-3">
{% block table %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>
</body>
</html>
......@@ -62,6 +62,50 @@ unittest.mock akan menghasilkan class Mock yang bisa digunakan untuk buat copyan
Patch akan berfungsi ketika kita replace fungsi send_mail ke fake_send_mail yang sesuai pada penjelasan di atas.
lalu mock_send_mail sebagai argumen yang dimasukan oleh patch function. Ketika melakukan test send_mail tidak dipanggil tetapi mock_send_mail yang akan terpanggil. Jadi ini membuat fungsi views tidak akan kirim email saat kita melakukan test tersebut
## Cerita Latihan8b mocking dapat membuat implementasi yang kita buat tightly coupled
Example pada contoh message sukses di account/views.py
def send_login_email(request):
email = request.POST['email']
token = Token.objects.create(email=email)
url = request.build_absolute_uri(
reverse('login') + '?token=' + str(token.uid)
)
messages.success(
request,
"Check your email, we've sent you a link you can use to log in."
)
di accounts/tests/test_views.py
def test_adds_success_message(self):
response = self.client.post(
"/accounts/send_login_email",
data={"email": "edith@example.com"},
follow=True,
)
message = list(response.context["messages"])[0]
self.assertEqual(
message.message,
"Check your email, we've sent you a link you can use to log in.",
)
self.assertEqual(message.tags, "success")
pada mock library
@patch("accounts.views.messages")
def test_adds_success_message_with_mocks(self, mock_messages):
response = self.client.post(
"/accounts/send_login_email", data={"email": "edith@example.com"}
)
expected = "Check your email, we've sent you a link you can use to log in."
self.assertEqual(
mock_messages.success.call_args, call(response.wsgi_request, expected)
)
Mocking akan membuat implementasi code yg kita bbuat menjadi tightly coupled karena mock sering test detail dri implementasi fungsi code.
## Cerita Latihan04 Prettification
Latihan ini bertujuan untuk implementasi secara increment, yang dimaksud adalah kita membuat perlahan perlahan tidak langsung semuanya dibuat. Lalu dilatihan 4 ini membuat styling yang membuat rusak functional test kita dan disini juga saya belaajar css pada aplikasi yang kita buat. Disini kita membuat static files juga u/ css untuk halaman menjadi lebih rapih dari sebelumnya. Mmebuat juga function action di form classs yang berada di home.html dan mengimplementasi function2 baru yang berada di class views.py yang membuat jika ada todo list terbaru dari user yang baru maka akan dibuatkan alamat url baru untuk user baru , jika user sudah ada dengan url tadi maka akan ditambahkan ke list todo yang ada.
......
......@@ -31,7 +31,7 @@ ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
# "django.contrib.admin",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
......@@ -41,10 +41,9 @@ INSTALLED_APPS = [
"accounts",
]
AUTH_USER_MODEL = 'accounts.User'
AUTHENTICATION_BACKENDS = [
'accounts.authentication.PasswordlessAuthenticationBackend',
]
AUTH_USER_MODEL = "accounts.User"
AUTHENTICATION_BACKENDS = ["accounts.authentication.PasswordlessAuthenticationBackend"]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
......@@ -118,6 +117,7 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
PROJECT_ROOT = os.path.join(os.path.abspath(__file__))
STATIC_URL = "/static/"
STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, "../static"))
......
Supports Markdown
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