From 7160a9c954aa1767fc329f35c0fd08f8230b12ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 20 Jan 2018 16:14:55 +0100 Subject: [PATCH] cof -- Add tests for registration views --- gestioncof/autocomplete.py | 7 + gestioncof/tests/test_views.py | 339 +++++++++++++++++++++++++++++++++ shared/tests/testcases.py | 32 ++++ 3 files changed, 378 insertions(+) create mode 100644 gestioncof/tests/test_views.py diff --git a/gestioncof/autocomplete.py b/gestioncof/autocomplete.py index 968398fd..9263dc50 100644 --- a/gestioncof/autocomplete.py +++ b/gestioncof/autocomplete.py @@ -21,6 +21,13 @@ class Clipper(object): self.clipper = clipper self.fullname = fullname + def __str__(self): + return '{} ({})'.format(self.clipper, self.fullname) + + def __eq__(self, other): + return ( + self.clipper == other.clipper and self.fullname == other.fullname) + @buro_required def autocomplete(request): diff --git a/gestioncof/tests/test_views.py b/gestioncof/tests/test_views.py new file mode 100644 index 00000000..60f93c9d --- /dev/null +++ b/gestioncof/tests/test_views.py @@ -0,0 +1,339 @@ +from django.contrib import messages +from django.contrib.auth import get_user_model +from django.contrib.messages.api import get_messages +from django.contrib.messages.storage.base import Message +from django.core import mail +from django.core.management import call_command +from django.test import TestCase, override_settings + +from gestioncof.autocomplete import Clipper +from gestioncof.models import Event +from gestioncof.tests.testcases import ViewTestCaseMixin + +from custommail.models import CustomMail + +from .utils import create_user, create_member + +User = get_user_model() + + +class RegistrationViewTests(ViewTestCaseMixin, TestCase): + url_name = 'registration' + url_expected = '/registration' + + http_methods = ['GET', 'POST'] + + auth_user = 'staff' + auth_forbidden = [None, 'user', 'member'] + + def requires_mails(self): + call_command('syncmails', verbosity=0) + + def test_get(self): + r = self.client.get(self.url) + self.assertEqual(r.status_code, 200) + + @property + def _minimal_data(self): + return { + 'first_name': '', + 'last_name': '', + 'email': '', + + # 'is_cof': '1', + 'login_clipper': '', + 'phone': '', + 'occupation': '1A', + 'departement': '', + 'type_cotiz': 'normalien', + 'comments': '', + + # 'user_exists': '1', + + 'events-TOTAL_FORMS': '0', + 'events-INITIAL_FORMS': '0', + 'events-MIN_NUM_FORMS': '0', + 'events-MAX_NUM_FORMS': '1000', + } + + def test_post_new(self): + self.requires_mails() + + r = self.client.post(self.url, dict(self._minimal_data, **{ + 'username': 'username', + 'first_name': 'first', + 'last_name': 'last', + 'email': 'username@mail.net', + 'is_cof': '1', + })) + + self.assertEqual(r.status_code, 200) + u = User.objects.get(username='username') + expected_message = Message(messages.SUCCESS, ( + "L'inscription de first last (username@mail.net) a été " + "enregistrée avec succès.\n" + "Il est désormais membre du COF n°{} !" + .format(u.pk) + )) + self.assertIn(expected_message, get_messages(r.wsgi_request)) + + self.assertEqual(u.first_name, 'first') + self.assertEqual(u.last_name, 'last') + self.assertEqual(u.email, 'username@mail.net') + + def test_post_edit(self): + self.requires_mails() + u = self.users['user'] + + r = self.client.post(self.url, dict(self._minimal_data, **{ + 'username': 'user', + 'first_name': 'first', + 'last_name': 'last', + 'email': 'user@mail.net', + 'is_cof': '1', + 'user_exists': '1', + })) + + self.assertEqual(r.status_code, 200) + u.refresh_from_db() + expected_message = Message(messages.SUCCESS, ( + "L'inscription de first last (user@mail.net) a été " + "enregistrée avec succès.\n" + "Il est désormais membre du COF n°{} !" + .format(u.pk) + )) + self.assertIn(expected_message, get_messages(r.wsgi_request)) + + self.assertEqual(u.first_name, 'first') + self.assertEqual(u.last_name, 'last') + self.assertEqual(u.email, 'user@mail.net') + + def _test_mail_welcome(self, was_cof, is_cof, expect_mail): + self.requires_mails() + u = self.users['member'] if was_cof else self.users['user'] + + data = dict(self._minimal_data, **{ + 'username': u.username, + 'email': 'user@mail.net', + 'user_exists': '1', + }) + if is_cof: + data['is_cof'] = '1' + self.client.post(self.url, data) + + u.refresh_from_db() + + def _is_sent(): + cm = CustomMail.objects.get(shortname='welcome') + welcome_msg = cm.get_message({'member': u}) + for m in mail.outbox: + if m.subject == welcome_msg.subject: + return True + return False + + self.assertEqual(_is_sent(), expect_mail) + + def test_mail_welcome_0(self): + self._test_mail_welcome(was_cof=False, is_cof=False, expect_mail=False) + + def test_mail_welcome_1(self): + self._test_mail_welcome(was_cof=False, is_cof=True, expect_mail=True) + + def test_mail_welcome_2(self): + self._test_mail_welcome(was_cof=True, is_cof=False, expect_mail=False) + + def test_mail_welcome_3(self): + self._test_mail_welcome(was_cof=True, is_cof=True, expect_mail=False) + + def test_events(self): + e = Event.objects.create() + + cf1 = e.commentfields.create(name='Comment Field 1') + cf2 = e.commentfields.create( + name='Comment Field 2', fieldtype='char', + ) + + o1 = e.options.create(name='Option 1') + o2 = e.options.create(name='Option 2', multi_choices=True) + + oc1 = o1.choices.create(value='O1 - Choice 1') + oc2 = o1.choices.create(value='O1 - Choice 2') + oc3 = o2.choices.create(value='O2 - Choice 1') + oc4 = o2.choices.create(value='O2 - Choice 2') + + self.client.post(self.url, dict(self._minimal_data, **{ + 'username': 'user', + 'user_exists': '1', + 'events-TOTAL_FORMS': '1', + 'events-INITIAL_FORMS': '0', + 'events-MIN_NUM_FORMS': '0', + 'events-MAX_NUM_FORMS': '1000', + 'events-0-status': 'paid', + 'events-0-option_{}'.format(o1.pk): [str(oc1.pk)], + 'events-0-option_{}'.format(o2.pk): [str(oc3.pk)], + 'events-0-comment_{}'.format(cf1.pk): 'comment 1', + 'events-0-comment_{}'.format(cf2.pk): '', + })) + + er = e.eventregistration_set.get(user=self.users['user']) + self.assertQuerysetEqual( + er.options.all(), map(repr, [oc1, oc3]), + ordered=False, + ) + self.assertCountEqual(er.comments.values_list('content', flat=True), [ + 'comment 1', + ]) + + +class RegistrationFormViewTests(ViewTestCaseMixin, TestCase): + urls_conf = [ + { + 'name': 'empty-registration', + 'expected': '/registration/empty', + }, + { + 'name': 'user-registration', + 'kwargs': {'username': 'user'}, + 'expected': '/registration/user/user', + }, + { + 'name': 'clipper-registration', + 'kwargs': { + 'login_clipper': 'uid', + 'fullname': 'First Last1 Last2', + }, + 'expected': '/registration/clipper/uid/First%20Last1%20Last2', + }, + ] + + auth_user = 'staff' + auth_forbidden = [None, 'user', 'member'] + + def get_initial(self, form, name): + return form.get_initial_for_field(form.fields[name], name) + + def test_empty(self): + r = self.client.get(self.t_urls[0]) + + user_form = r.context['user_form'] + profile_form = r.context['profile_form'] + events_form = r.context['event_formset'] + clubs_form = r.context['clubs_form'] + + def test_username(self): + u = self.users['user'] + u.first_name = 'first' + u.last_name = 'last' + u.save() + + r = self.client.get(self.t_urls[1]) + + user_form = r.context['user_form'] + profile_form = r.context['profile_form'] + events_form = r.context['event_formset'] + clubs_form = r.context['clubs_form'] + + self.assertEqual(self.get_initial(user_form, 'username'), 'user') + self.assertEqual(self.get_initial(user_form, 'first_name'), 'first') + self.assertEqual(self.get_initial(user_form, 'last_name'), 'last') + + def test_clipper(self): + r = self.client.get(self.t_urls[2]) + + user_form = r.context['user_form'] + profile_form = r.context['profile_form'] + events_form = r.context['event_formset'] + clubs_form = r.context['clubs_form'] + + self.assertEqual(self.get_initial(user_form, 'first_name'), 'First') + self.assertEqual( + self.get_initial(user_form, 'last_name'), 'Last1 Last2') + self.assertEqual( + self.get_initial(user_form, 'email'), 'uid@clipper.ens.fr') + self.assertEqual( + self.get_initial(profile_form, 'login_clipper'), 'uid') + + +@override_settings(LDAP_SERVER_URL='ldap_url') +class RegistrationAutocompleteViewTests(ViewTestCaseMixin, TestCase): + url_name = 'cof.registration.autocomplete' + url_expected = '/autocomplete/registration' + + auth_user = 'staff' + auth_forbidden = [None, 'user', 'member'] + + def setUp(self): + super().setUp() + + self.u1 = create_user('uu_u1', attrs={ + 'first_name': 'abc', 'last_name': 'xyz', + }) + self.u2 = create_user('uu_u2', attrs={ + 'first_name': 'wyz', 'last_name': 'abd', + }) + self.m1 = create_member('uu_m1', attrs={ + 'first_name': 'ebd', 'last_name': 'wyv', + }) + + self.mockLDAP([]) + + def _test( + self, query, expected_users, expected_members, expected_clippers, + ): + r = self.client.get(self.url, {'q': query}) + + self.assertEqual(r.status_code, 200) + + self.assertQuerysetEqual( + r.context['users'], map(repr, expected_users), + ordered=False, + ) + self.assertQuerysetEqual( + r.context['members'], + map(lambda u: repr(u.profile), expected_members), + ordered=False, + ) + self.assertCountEqual( + map(str, r.context.get('clippers', [])), + map(str, expected_clippers), + ) + + def test_username(self): + self._test('uu', [self.u1, self.u2], [self.m1], []) + + def test_firstname(self): + self._test('ab', [self.u1, self.u2], [], []) + + def test_lastname(self): + self._test('wy', [self.u2], [self.m1], []) + + def test_multi_query(self): + self._test('wy bd', [self.u2], [self.m1], []) + + def test_clipper(self): + mock_ldap = self.mockLDAP([('uid', 'first last')]) + + self._test('aa bb', [], [], [Clipper('uid', 'first last')]) + + mock_ldap.search.assert_called_once_with( + 'dc=spi,dc=ens,dc=fr', + '(&(|(cn=*aa*)(uid=*aa*))(|(cn=*bb*)(uid=*bb*)))', + attributes=['uid', 'cn'], + ) + + def test_clipper_escaped(self): + mock_ldap = self.mockLDAP([]) + + self._test('; & | (', [], [], []) + + mock_ldap.search.assert_not_called() + + def test_clipper_no_duplicate(self): + self.mockLDAP([('uid', 'uu_u1')]) + + self._test('uu u1', [self.u1], [], [Clipper('uid', 'uu_u1')]) + + self.u1.profile.login_clipper = 'uid' + self.u1.profile.save() + + self._test('uu u1', [self.u1], [], []) diff --git a/shared/tests/testcases.py b/shared/tests/testcases.py index 15792383..03e63e6b 100644 --- a/shared/tests/testcases.py +++ b/shared/tests/testcases.py @@ -92,6 +92,38 @@ class TestCaseMixin: else: self.assertEqual(actual, expected) + def mockLDAP(self, results): + class Elt: + def __init__(self, value): + self.value = value + + class Entry: + def __init__(self, **kwargs): + for k, v in kwargs.items(): + setattr(self, k, Elt(v)) + + results_as_ldap = [ + Entry(uid=uid, cn=name) for uid, name in results + ] + + mock_connection = mock.MagicMock() + mock_connection.entries = results_as_ldap + + # Connection is used as a context manager. + mock_context_manager = mock.MagicMock() + mock_context_manager.return_value.__enter__.return_value = ( + mock_connection + ) + + patcher = mock.patch( + 'gestioncof.autocomplete.Connection', + new=mock_context_manager, + ) + patcher.start() + self.addCleanup(patcher.stop) + + return mock_connection + class ViewTestCaseMixin(TestCaseMixin): """