Skip to content

Commit

Permalink
kompletigas testojn de ensaluta vido kaj aldonas testojn de elsaluta …
Browse files Browse the repository at this point in the history
…vido
  • Loading branch information
interDist committed Aug 30, 2023
1 parent ea2fffb commit e497b55
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 9 deletions.
2 changes: 1 addition & 1 deletion core/templates/registration/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{% block form_block_class %} login{% endblock %}

{% block fields_after %}
<p class="pull-left text-left keep-margin">
<p class="pull-left text-left keep-margin recovery">
{% url 'password_reset' as password_reset_url %}{% url 'username_remind' as username_remind_url %}
{% blocktrans with pwd_url=password_reset_url usr_url=username_remind_url trimmed %}
I forgot <a href="{{ pwd_url }}">my password</a> or <a href="{{ usr_url }}">my username</a>
Expand Down
6 changes: 5 additions & 1 deletion core/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.conf import settings
from django.contrib.auth.views import (
LogoutView, PasswordResetCompleteView, PasswordResetDoneView,
)
Expand Down Expand Up @@ -35,7 +36,10 @@
AccountRestoreRequestView.as_view(), name='login_restore'),
path(
pgettext_lazy("URL", 'logout/'),
LogoutView.as_view(next_page='/'), name='logout'),
LogoutView.as_view(
next_page='/', redirect_field_name=settings.REDIRECT_FIELD_NAME,
),
name='logout'),

path(
pgettext_lazy("URL", 'agreement/'), include([
Expand Down
Empty file added tests/functional/__init__.py
Empty file.
65 changes: 65 additions & 0 deletions tests/functional/test_account.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import re

from django.core import mail
from django.test import override_settings, tag
from django.urls import reverse, reverse_lazy

from django_webtest import WebTest

from ..assertions import AdditionalAsserts
from ..factories import UserFactory


@tag('functional', 'views', 'views-session', 'views-login')
class InactiveUserLoginTests(AdditionalAsserts, WebTest):
@classmethod
def setUpTestData(cls):
cls.url = reverse_lazy('login')
cls.user = UserFactory(profile=None, is_active=False)

def login_attempt_tests(self, lang):
# A user who supplied the correct credentials but whose account was
# deactivated, is expected to be denied login.
# A warning is expected to be recorded in the authentication log,
# containing the restore_request_id; the same id is expected in the
# email sent to the administrators once the user clicks the link to
# notify them about the user's desire to reactivate the account.

page = self.app.get(self.url, status=200)
page.form['username'] = self.user.username
page.form['password'] = "adm1n"
with self.assertLogs('PasportaServo.auth', level='WARNING') as log:
result_page = page.form.submit()
# A status code of 200 means the user is returned to the login page
# with an error; otherwise the status code would have been 302.
self.assertEqual(result_page.status_code, 200)
self.assertLength(log.records, 1)
m = re.search(r'\[([A-F0-9-]+)\]', log.output[0])
self.assertIsNotNone(m, msg="restore_request_id was not logged.")
notification_id = m.group(1)
mail.outbox = []
# Simulate a click on the "request reactivation" link.
status_page = result_page.click(href=lambda href: href == reverse('login_restore'))
self.assertEqual(len(mail.outbox), 1)
self.assertIn(
{
'en': "Note to admin: User requests to reactivate their account",
'eo': "Sciigo al admino: Uzanto petas reaktivigi sian PS-konton",
}[lang],
mail.outbox[0].subject
)
self.assertIn(notification_id, mail.outbox[0].subject)
self.assertEqual(status_page.status_code, 200)
self.assertContains(
status_page,
{
'en': "An administrator will contact you soon.",
'eo': "Administranto baldaŭ kontaktiĝos kun vi.",
}[lang]
)

def test_login(self):
for lang in ['en', 'eo']:
with override_settings(LANGUAGE_CODE=lang):
with self.subTest(lang=lang):
self.login_attempt_tests(lang)
114 changes: 107 additions & 7 deletions tests/views/test_session_views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from uuid import uuid4

from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.test import modify_settings, override_settings, tag
from django.urls import reverse_lazy

Expand Down Expand Up @@ -85,7 +86,27 @@ def test_login_form(self):
page = self.app.get(self.url, status=200)
self.assertEqual(page.pyquery(form_title_selector).text(), "Ensaluto")

# TODO: Test "Mi forgesis mian pasvorton aŭ mian salutnomon".
def test_recovery_options(self):
# The view is expected to provide recovery / reminder options to the
# user, for the access password and the username.
test_data = {
'en': "I forgot my password or my username",
'eo': "Mi forgesis mian pasvorton aŭ mian salutnomon",
}
expected_urls = [reverse_lazy('password_reset'), reverse_lazy('username_remind')]
for lang in test_data:
with self.subTest(lang=lang):
with override_settings(LANGUAGE_CODE=lang):
page = self.app.get(self.url, status=200)
recovery_elem = page.pyquery(".base-form.login form .recovery")
self.assertEqual(recovery_elem.text(), test_data[lang])
recovery_option_elems = recovery_elem.children("a")
for i, expected_recovery_option_url in enumerate(expected_urls):
with self.subTest(option=recovery_option_elems.eq(i).text()):
self.assertEqual(
recovery_option_elems.eq(i).attr("href"),
expected_recovery_option_url
)

def incorrect_credentials_tests(self, expected_error):
# The view is expected to show a form error when incorrect credentials
Expand Down Expand Up @@ -189,7 +210,7 @@ def test_redirect_if_logged_in(self):

# Verify fallback support for third-party libraries that do not use
# the customized next page parameter's name. The view is expected to
# redirect to the desitnation provided in the 'next' parameter.
# redirect to the destination provided in the 'next' parameter.
page = self.app.get(
f'{self.url}?next=/there-and-beyond',
user=self.user)
Expand Down Expand Up @@ -235,7 +256,7 @@ def inactive_user_tests(self, inactive_user, expected_errors):
page = page.form.submit()
self.assertEqual(page.status_code, 200)
self.assertTrue('form' in page.context)
self.assertEqual(len(page.context['form'].non_field_errors()), 2)
self.assertLength(page.context['form'].non_field_errors(), 2)
self.assertEqual(
page.context['form'].non_field_errors()[0],
expected_errors[0]
Expand All @@ -248,10 +269,13 @@ def inactive_user_tests(self, inactive_user, expected_errors):
expected_errors[2],
page.context['form'].non_field_errors()[1]
)
# TODO test that warning is logged.
# TODO the log record should contain the "notification id".
# TODO test click on "Informi administranton".
# TODO the new email should contain the "notification id".
notification_link_target = [
elem.attr("href")
for elem in page.pyquery(".base-form.login form .alert > a").items()
if elem.text() == expected_errors[2]
]
self.assertLength(notification_link_target, 1)
self.assertEqual(notification_link_target[0], reverse_lazy('login_restore'))

def test_inactive_user(self):
inactive_user = UserFactory(profile=None, is_active=False)
Expand Down Expand Up @@ -279,3 +303,79 @@ def test_inactive_user(self):
"Informi administranton.",
)
)


@tag('views', 'views-session', 'views-logout')
class LogoutViewTests(WebTest):
@classmethod
def setUpTestData(cls):
cls.url = reverse_lazy('logout')
cls.user = UserFactory(profile=None)

def test_view_url(self):
# Verify that the view can be found at the expected URL.
response = self.app.get(self.url, status='*')
self.assertEqual(response.status_code, 302)

test_data = {
'en': '/logout/',
'eo': '/elsaluti/',
}
for lang, expected_url in test_data.items():
with self.subTest(lang=lang, attempted=expected_url):
with override_settings(LANGUAGE_CODE=lang):
response = self.app.get(expected_url, status='*')
self.assertEqual(response.status_code, 302)

def test_method(self):
# Verify that logging out via a GET request is possible.
page = self.app.get(self.url, user=self.user).maybe_follow()
self.assertTrue('user' in page.context)
self.assertEqual(page.context['user'], AnonymousUser())

# Verify that logging out via a POST request is possible.
page = self.app.get('/', user=self.user)
page = self.app.post(
self.url,
{
'csrfmiddlewaretoken': page.context['csrf_token'],
},
user=self.user)
page = page.maybe_follow()
self.assertTrue('user' in page.context)
self.assertEqual(page.context['user'], AnonymousUser())

def redirect_tests(self, user):
# The view is expected to redirect to the home page.
page = self.app.get(self.url, status=302, user=user)
self.assertEqual(page.location, '/')

# The view is expected to redirect to the provided destination when
# the next page parameter is included.
page = self.app.get(
f'{self.url}?{settings.REDIRECT_FIELD_NAME}=/another/page/',
status=302,
user=user)
self.assertEqual(page.location, '/another/page/')

# The view is expected to ignore the destination provided in the
# 'next' parameter and redirect to the home page.
page = self.app.get(
f'{self.url}?next=/another/page/',
status=302,
user=user)
self.assertEqual(page.location, '/')

# The provided destination is expected to be discarded when it is
# not within the website.
page = self.app.get(
f'{self.url}?{settings.REDIRECT_FIELD_NAME}=https://far.away/',
auto_follow=True,
user=user)
self.assertEqual(page.request.path, '/')

def test_redirect_unauthenticated_user(self):
self.redirect_tests(user=None)

def test_redirect_logged_in_user(self):
self.redirect_tests(user=self.user)

0 comments on commit e497b55

Please sign in to comment.