forked from DGNum/gestioCOF
Merge branch 'aureplop/cof-tests_registration' into 'master'
cof -- Add tests for registration views See merge request cof-geek/gestioCOF!287
This commit is contained in:
commit
b39b6d6bb3
3 changed files with 372 additions and 7 deletions
|
@ -19,6 +19,13 @@ class Clipper(object):
|
||||||
self.clipper = clipper
|
self.clipper = clipper
|
||||||
self.fullname = fullname
|
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
|
@buro_required
|
||||||
def autocomplete(request):
|
def autocomplete(request):
|
||||||
|
|
|
@ -3,19 +3,344 @@ import uuid
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.contrib import messages
|
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.api import get_messages
|
||||||
from django.contrib.messages.storage.base import Message
|
from django.contrib.messages.storage.base import Message
|
||||||
from django.test import Client, TestCase
|
from django.core import mail
|
||||||
|
from django.core.management import call_command
|
||||||
|
from django.test import Client, TestCase, override_settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from bda.models import Salle, Tirage
|
from bda.models import Salle, Tirage
|
||||||
|
from gestioncof.autocomplete import Clipper
|
||||||
from gestioncof.models import (
|
from gestioncof.models import (
|
||||||
CalendarSubscription, Club, Event, Survey, SurveyAnswer
|
CalendarSubscription, Club, Event, Survey, SurveyAnswer
|
||||||
)
|
)
|
||||||
from gestioncof.tests.testcases import ViewTestCaseMixin
|
from gestioncof.tests.testcases import ViewTestCaseMixin
|
||||||
|
|
||||||
|
from custommail.models import CustomMail
|
||||||
|
|
||||||
from .utils import create_member, create_root, create_user
|
from .utils import create_member, create_root, create_user
|
||||||
|
|
||||||
|
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 (<tt>username@mail.net</tt>) 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 (<tt>user@mail.net</tt>) 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')
|
||||||
|
o1.choices.create(value='O1 - Choice 2')
|
||||||
|
oc3 = o2.choices.create(value='O2 - Choice 1')
|
||||||
|
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 test_empty(self):
|
||||||
|
r = self.client.get(self.t_urls[0])
|
||||||
|
|
||||||
|
self.assertIn('user_form', r.context)
|
||||||
|
self.assertIn('profile_form', r.context)
|
||||||
|
self.assertIn('event_formset', r.context)
|
||||||
|
self.assertIn('clubs_form', r.context)
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
|
self.assertIn('user_form', r.context)
|
||||||
|
self.assertIn('profile_form', r.context)
|
||||||
|
self.assertIn('event_formset', r.context)
|
||||||
|
self.assertIn('clubs_form', r.context)
|
||||||
|
user_form = r.context['user_form']
|
||||||
|
self.assertEqual(user_form['username'].initial, 'user')
|
||||||
|
self.assertEqual(user_form['first_name'].initial, 'first')
|
||||||
|
self.assertEqual(user_form['last_name'].initial, 'last')
|
||||||
|
|
||||||
|
def test_clipper(self):
|
||||||
|
r = self.client.get(self.t_urls[2])
|
||||||
|
|
||||||
|
self.assertIn('user_form', r.context)
|
||||||
|
self.assertIn('profile_form', r.context)
|
||||||
|
self.assertIn('event_formset', r.context)
|
||||||
|
self.assertIn('clubs_form', r.context)
|
||||||
|
user_form = r.context['user_form']
|
||||||
|
profile_form = r.context['profile_form']
|
||||||
|
self.assertEqual(user_form['first_name'].initial, 'First')
|
||||||
|
self.assertEqual(user_form['last_name'].initial, 'Last1 Last2')
|
||||||
|
self.assertEqual(user_form['email'].initial, 'uid@clipper.ens.fr')
|
||||||
|
self.assertEqual(profile_form['login_clipper'].initial, '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], [], [])
|
||||||
|
|
||||||
|
|
||||||
class HomeViewTests(ViewTestCaseMixin, TestCase):
|
class HomeViewTests(ViewTestCaseMixin, TestCase):
|
||||||
url_name = 'home'
|
url_name = 'home'
|
||||||
|
@ -458,9 +783,10 @@ class CalendarViewTests(ViewTestCaseMixin, TestCase):
|
||||||
fermeture=self.now,
|
fermeture=self.now,
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
l = Salle.objects.create()
|
location = Salle.objects.create()
|
||||||
s = t.spectacle_set.create(
|
s = t.spectacle_set.create(
|
||||||
date=self.now, price=3.5, slots=20, location=l, listing=True)
|
date=self.now, price=3.5, slots=20, location=location,
|
||||||
|
listing=True)
|
||||||
|
|
||||||
r = self.client.post(self.url, {'other_shows': [str(s.pk)]})
|
r = self.client.post(self.url, {'other_shows': [str(s.pk)]})
|
||||||
|
|
||||||
|
@ -491,17 +817,17 @@ class CalendarICSViewTests(ViewTestCaseMixin, TestCase):
|
||||||
fermeture=self.now,
|
fermeture=self.now,
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
l = Salle.objects.create(name='Location')
|
location = Salle.objects.create(name='Location')
|
||||||
self.s1 = self.t.spectacle_set.create(
|
self.s1 = self.t.spectacle_set.create(
|
||||||
price=1, slots=10, location=l, listing=True,
|
price=1, slots=10, location=location, listing=True,
|
||||||
title='Spectacle 1', date=self.now + timedelta(days=1),
|
title='Spectacle 1', date=self.now + timedelta(days=1),
|
||||||
)
|
)
|
||||||
self.s2 = self.t.spectacle_set.create(
|
self.s2 = self.t.spectacle_set.create(
|
||||||
price=2, slots=20, location=l, listing=True,
|
price=2, slots=20, location=location, listing=True,
|
||||||
title='Spectacle 2', date=self.now + timedelta(days=2),
|
title='Spectacle 2', date=self.now + timedelta(days=2),
|
||||||
)
|
)
|
||||||
self.s3 = self.t.spectacle_set.create(
|
self.s3 = self.t.spectacle_set.create(
|
||||||
price=3, slots=30, location=l, listing=True,
|
price=3, slots=30, location=location, listing=True,
|
||||||
title='Spectacle 3', date=self.now + timedelta(days=3),
|
title='Spectacle 3', date=self.now + timedelta(days=3),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,38 @@ class TestCaseMixin:
|
||||||
else:
|
else:
|
||||||
self.assertEqual(actual, expected)
|
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
|
||||||
|
|
||||||
def load_from_csv_response(self, r):
|
def load_from_csv_response(self, r):
|
||||||
decoded = r.content.decode('utf-8')
|
decoded = r.content.decode('utf-8')
|
||||||
return list(csv.reader(decoded.split('\n')[:-1]))
|
return list(csv.reader(decoded.split('\n')[:-1]))
|
||||||
|
|
Loading…
Reference in a new issue