diff --git a/README.md b/README.md index 3fcc5cbb749e60877073f34fb863203e2c45645c..28ab6e806e9d3d6a4bce1a4ff3186d301dbf8b8c 100644 --- a/README.md +++ b/README.md @@ -206,4 +206,33 @@ Karena mutation score dari test adalah 100%, maka tidak perlu menambahkan test c 1. Menggunakan mock library menghasilkan code yang lebih clean. 2. Dalam mock library, cukup menggunakan decorator `patch` untuk menunjuk object yang ingin di-mock. Setelah test yang terdapat decorator tersebut dijalankan, object yang di-mock akan kembali ke bentuk awalnya sehingga tidak merubah object dalam test lain. Sementara dalam monkeypatching object tidak kembali ke keadaan awalnya sehingga dapat merusak test lain. 3. Mock library dapat me-record behaviour dari mock object yang dipanggil. -4. Mock library dapat me-return value spesifik dengan `return_value`, dan raise exception dengan `side_effect`. \ No newline at end of file +4. Mock library dapat me-return value spesifik dengan `return_value`, dan raise exception dengan `side_effect`. + +### Mock Tightly Coupled Pada Implementasi +Dalam testing sebaiknya yang dites adalah behaviour-nya, bukan implementasinya. Namun dalam mocking, hal tersebut tidak dapat direalisasikan. Contohnya dalam kode +```python +from unittest.mock import patch, call +[...] + + @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), + ) +``` + +Implementasinya: + +```python + messages.add_message( + request, + messages.SUCCESS, + "Check your email, we've sent you a link you can use to log in." +``` +Dalam test nonmock akan pass, namun dalam test mock akan fail. Ini terjadi karena object yang di-mock adalah `accounts.views.messages` dan yang digunakan untuk assert adalah `messages.success`. Sementara dalam implementasi digunakan `messages.add_messages`. Sehingga meskipun hasil yang didapatkan sama, test yang dijalankan akan terus fail. \ No newline at end of file diff --git a/accounts/models.py b/accounts/models.py index 4a5e618e97ee8b1c5890f0664d398dd9d77d9cb1..9a2a34c64fea333cf696121eacdfbab914ad3775 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -2,8 +2,12 @@ from django.db import models from django.contrib.auth.models import ( AbstractBaseUser, BaseUserManager, PermissionsMixin ) +from django.contrib import auth import uuid +auth.signals.user_logged_in.disconnect(auth.models.update_last_login) + + class Token(models.Model): email = models.EmailField() diff --git a/accounts/tests/test_models.py b/accounts/tests/test_models.py index 79a3a3a61f4ab6fd5f403c34bfaed7fcefc20271..e4dc10efb55a7d86853039b6b3bd3dcc025c00c2 100644 --- a/accounts/tests/test_models.py +++ b/accounts/tests/test_models.py @@ -1,8 +1,8 @@ from accounts.models import Token from django.test import TestCase -from django.contrib.auth import get_user_model +from django.contrib import auth -User = get_user_model() +User = auth.get_user_model() class UserModelTest(TestCase): @@ -11,6 +11,12 @@ class UserModelTest(TestCase): user = User(email='a@b.com') user.full_clean() # should not raise + 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) + class TokenModelTest(TestCase): def test_links_user_with_auto_generated_uid(self): diff --git a/accounts/urls.py b/accounts/urls.py index 52fbebb7b6257905b529afc208b970d2cbb23308..f0ea2689eef312b56ccaa8de162720f1a7ee5955 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -1,4 +1,6 @@ from django.conf.urls import url +# from django.contrib.auth import logout + from accounts import views urlpatterns = [ diff --git a/functional_tests/test_login.py b/functional_tests/test_login.py index 1d86b19f474742b0cb99757266e0f8f2fce70a7f..dd431d6d66f2dc4f74185445d394de297cc99504 100644 --- a/functional_tests/test_login.py +++ b/functional_tests/test_login.py @@ -45,4 +45,14 @@ class LoginTest(FunctionalTest): # 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) \ No newline at end of file + # 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) \ No newline at end of file diff --git a/lists/templates/base.html b/lists/templates/base.html index d3cc5338a993b1ee18ce22e997f9276f8474e71d..d3bed5f1d9b13bf9004e61ae0c823af38de995da 100644 --- a/lists/templates/base.html +++ b/lists/templates/base.html @@ -16,19 +16,25 @@ <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> - {% else %} - <form class="navbar-form navbar-right" - method="POST" - action="{% url 'send_login_email' %}"> - Enter email to log in: <input name="email" type="text" /> - {% csrf_token %} - </form> - {% endif %} - </div> + <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="{% url 'logout' %}">Log out</a></li> + </ul> + {% else %} + <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> + </nav> {% if messages %} <div class="row">