members/tests: add more admin tests

toml-configuration-with-templates
Christian Merten 11 months ago
parent 9610503caa
commit d1075f43e7
Signed by: christian.merten
GPG Key ID: D953D69721B948B3

@ -5,6 +5,8 @@ from django.contrib.auth import models as authmodels
from django.contrib.admin.sites import AdminSite from django.contrib.admin.sites import AdminSite
from django.contrib.messages import get_messages from django.contrib.messages import get_messages
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib import admin
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.test import TestCase, Client, RequestFactory from django.test import TestCase, Client, RequestFactory
from django.utils import timezone, translation from django.utils import timezone, translation
@ -14,9 +16,11 @@ from django import template
from unittest import skip, mock from unittest import skip, mock
from .models import Member, Group, PermissionMember, PermissionGroup, Freizeit, GEMEINSCHAFTS_TOUR, MUSKELKRAFT_ANREISE,\ from .models import Member, Group, PermissionMember, PermissionGroup, Freizeit, GEMEINSCHAFTS_TOUR, MUSKELKRAFT_ANREISE,\
MemberNoteList, NewMemberOnList, confirm_mail_by_key, EmergencyContact, MemberWaitingList,\ MemberNoteList, NewMemberOnList, confirm_mail_by_key, EmergencyContact, MemberWaitingList,\
RegistrationPassword, MemberUnconfirmedProxy, InvitationToGroup, DIVERSE, MALE, FEMALE RegistrationPassword, MemberUnconfirmedProxy, InvitationToGroup, DIVERSE, MALE, FEMALE,\
Klettertreff, KlettertreffAttendee
from .admin import MemberWaitingListAdmin, MemberAdmin, FreizeitAdmin, MemberNoteListAdmin,\ from .admin import MemberWaitingListAdmin, MemberAdmin, FreizeitAdmin, MemberNoteListAdmin,\
MemberUnconfirmedAdmin MemberUnconfirmedAdmin, RegistrationFilter, FilteredMemberFieldMixin,\
MemberAdminForm, StatementOnListForm, KlettertreffAdmin, GroupAdmin
from .pdf import fill_pdf_form, render_tex, media_path, serve_pdf, find_template, merge_pdfs from .pdf import fill_pdf_form, render_tex, media_path, serve_pdf, find_template, merge_pdfs
from mailer.models import EmailAddress from mailer.models import EmailAddress
from finance.models import Statement, Bill from finance.models import Statement, Bill
@ -331,6 +335,7 @@ class MemberAdminTestCase(AdminTestCase):
m.group.add(mega_kids) m.group.add(mega_kids)
m.save() m.save()
self.fritz = cool_kids.member_set.first() self.fritz = cool_kids.member_set.first()
self.peter = mega_kids.member_set.first()
def test_changelist(self): def test_changelist(self):
c = self._login('superuser') c = self._login('superuser')
@ -454,21 +459,95 @@ class MemberAdminTestCase(AdminTestCase):
c = self._login('superuser') c = self._login('superuser')
response = c.post(reverse('admin:members_member_inviteasuser', args=(12345,))) # expect: user does not exist
self.assertEqual(response.status_code, HTTPStatus.FOUND) response = c.post(reverse('admin:members_member_inviteasuser', args=(12345,)), follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Member not found.'))
response = c.post(url) # expect: user is found, but email address is not internal
self.assertEqual(response.status_code, HTTPStatus.FOUND) response = c.post(url, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertFalse(self.fritz.has_internal_email())
self.assertContains(response,
_("The configured email address for %(name)s is not an internal one.") % {'name': str(self.fritz)})
# update email to allowed email domain
self.fritz.email = 'foobar@{domain}'.format(domain=settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0]) self.fritz.email = 'foobar@{domain}'.format(domain=settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0])
self.fritz.save() self.fritz.save()
response = c.post(url) response = c.post(url)
# expect: user is found and confirmation page is shown
self.assertEqual(response.status_code, HTTPStatus.OK) self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Invite'))
# expect: user is invited
response = c.post(url, data={'apply': ''}) response = c.post(url, data={'apply': ''})
self.assertEqual(response.status_code, HTTPStatus.FOUND) self.assertEqual(response.status_code, HTTPStatus.FOUND)
# expect: user already has a pending invitation
response = c.post(url) response = c.post(url)
self.assertEqual(response.status_code, HTTPStatus.OK) self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response,
_('%(name)s already has a pending invitation as user.' % {'name': str(self.fritz)}))
# set user
u = User.objects.create(username='fritzuser', password='secret')
self.fritz.user = u
self.fritz.save()
# expect: user already has an account
response = c.post(url, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _("%(name)s already has login data.") % {'name': str(self.fritz)})
def test_invite_as_user_action(self):
qs = Member.objects.all()
url = reverse('admin:members_member_changelist')
# expect: confirmation view
c = self._login('superuser')
response = c.post(url, data={'action': 'invite_as_user_action',
'_selected_action': [self.fritz.pk]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Invite'))
# confirm invite, expect: partial success
response = c.post(url, data={'action': 'invite_as_user_action',
'_selected_action': [self.fritz.pk], 'apply': True}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Some members have been invited, others could not be invited.'))
# confirm invite, expect: success
self.peter.email = 'foobar@{domain}'.format(domain=settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0])
self.peter.save()
self.fritz.email = 'foobar@{domain}'.format(domain=settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0])
self.fritz.save()
response = c.post(url, data={'action': 'invite_as_user_action',
'_selected_action': [self.fritz.pk, self.peter.pk], 'apply': True}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Successfully invited selected members to join as users.'))
def test_send_mail_to(self):
# this is not connected to an action currently
qs = Member.objects.all()
response = self.admin.send_mail_to(None, qs)
self.assertEqual(response.status_code, HTTPStatus.FOUND)
def test_request_echo(self):
self.peter.gets_newsletter = False
self.peter.save()
url = reverse('admin:members_member_changelist')
# expect: success
c = self._login('superuser')
response = c.post(url, data={'action': 'request_echo',
'_selected_action': [self.fritz.pk, self.peter.pk]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
def test_activity_score(self):
# manually set activity score
for i in range(5):
self.fritz._activity_score = i * 10 - 1
self.assertTrue('img' in self.admin.activity_score(self.fritz))
class FreizeitTestCase(BasicMemberTestCase): class FreizeitTestCase(BasicMemberTestCase):
@ -1399,3 +1478,221 @@ class EchoViewTestCase(BasicMemberTestCase):
)) ))
self.assertEqual(response.status_code, HTTPStatus.OK) self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Your data was successfully updated.')) self.assertContains(response, _('Your data was successfully updated.'))
class TestRegistrationFilterTestCase(AdminTestCase):
def setUp(self):
super().setUp(model=Member, admin=MemberAdmin)
def test_lookups(self):
fil = RegistrationFilter(None, {}, Member, self.admin)
self.assertTrue(('All', _('All')) in fil.lookups(None, None))
def test_queryset_no_filter(self):
qs = Member.objects.all()
# filtering with All returns passed queryset
fil = RegistrationFilter(None, {'registration_complete': 'All'}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs), qs, ordered=False)
# or with None
fil = RegistrationFilter(None, {}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs), qs, ordered=False)
@skip("Currently errors, because 'registration_complete' is not a field.")
def test_queryset_filter(self):
qs = Member.objects.all()
fil = RegistrationFilter(None, {'registration_complete': 'True'}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs),
Member.objects.filter(registration_complete=True),
ordered=False)
fil = RegistrationFilter(None, {'registration_complete': 'False'}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs),
Member.objects.filter(registration_complete=True),
ordered=False)
fil = RegistrationFilter(None, {}, Member, self.admin)
fil.default_value = ('True', True)
self.assertQuerysetEqual(fil.queryset(None, qs),
Member.objects.filter(registration_complete=True),
ordered=False)
class MemberAdminFormTestCase(TestCase):
def test_clean_iban(self):
form_data = dict(REGISTRATION_DATA, iban='foobar')
form = MemberAdminForm(data=form_data)
self.assertTrue('IBAN' in str(form.errors))
form_data = dict(REGISTRATION_DATA, iban='DE89370400440532013000')
form = MemberAdminForm(data=form_data)
self.assertFalse('IBAN' in str(form.errors))
class StatementOnListFormTestCase(BasicMemberTestCase):
def setUp(self):
super().setUp()
self.ex = Freizeit.objects.create(name='Wild trip', kilometers_traveled=120,
tour_type=GEMEINSCHAFTS_TOUR,
tour_approach=MUSKELKRAFT_ANREISE,
difficulty=1)
self.ex.jugendleiter.add(self.fritz)
self.ex.save()
self.st = Statement.objects.create(excursion=self.ex, night_cost=42, subsidy_to=None)
self.st.allowance_to.add(self.fritz)
self.st.save()
def test_clean(self):
form = StatementOnListForm(parent_obj=self.ex, instance=self.st)
# should not raise any error
form.cleaned_data = {'excursion': self.ex,
'allowance_to': None}
form.clean()
# should raise Validation error because too many allowance_to are listed
form.cleaned_data = {'excursion': self.ex,
'allowance_to': Member.objects.filter(pk=self.fritz.pk)}
self.assertGreater(1, self.ex.approved_staff_count)
self.assertRaises(ValidationError, form.clean)
class KlettertreffAdminTestCase(AdminTestCase):
def setUp(self):
super().setUp(model=Klettertreff, admin=KlettertreffAdmin)
cool_kids = Group.objects.get(name='cool kids')
for i in range(10):
kl = Klettertreff.objects.create(location='foo', topic='bar', group=cool_kids)
def test_change(self):
kl = Klettertreff.objects.first()
url = reverse('admin:members_klettertreff_change', args=(kl.pk,))
c = self._login('superuser')
response = c.get(url)
self.assertEqual(response.status_code, HTTPStatus.OK)
def test_overview(self):
qs = Klettertreff.objects.all()
url = reverse('admin:members_klettertreff_changelist')
# expect: success
c = self._login('superuser')
response = c.post(url, data={'action': 'overview',
'_selected_action': [kl.pk for kl in qs]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
# expect: success and filtered by group, this does not work
c = self._login('superuser')
response = c.post(url, data={'action': 'overview',
'group__name': 'cool kids',
'_selected_action': [kl.pk for kl in qs]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
class GroupAdminTestCase(AdminTestCase):
def setUp(self):
super().setUp(model=Group, admin=GroupAdmin)
def test_change(self):
g = Group.objects.first()
url = reverse('admin:members_group_change', args=(g.pk,))
c = self._login('superuser')
response = c.get(url)
self.assertEqual(response.status_code, HTTPStatus.OK)
class FilteredMemberFieldMixinTestCase(AdminTestCase):
def setUp(self):
class CustomGroupAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
class CustomMemberAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
class CustomMemberAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
class CustomKlettertreffAttendeeAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
self.custom_gr_admin = CustomGroupAdmin(Group, AdminSite())
self.custom_member_admin = CustomMemberAdmin(Member, AdminSite())
self.custom_kla_admin = CustomKlettertreffAttendeeAdmin(KlettertreffAttendee, AdminSite())
super().setUp(model=Group, admin=CustomGroupAdmin)
User.objects.create_user(
username='foobar', password='secret'
)
def test_invalid_manytomany(self):
# filtering a db_field with related model != Member should return the db_field unchanged
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
request.user = User.objects.get(username='superuser')
db_field = Member._meta.get_field('group')
member_admin = MemberAdmin(Member, AdminSite())
self.assertQuerysetEqual(self.custom_member_admin.formfield_for_manytomany(db_field, request).queryset,
member_admin.formfield_for_manytomany(db_field, request).queryset,
ordered=False)
def test_invalid_foreignkey(self):
# filtering a db_field with related model != Member should return the db_field unchanged
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
request.user = User.objects.get(username='superuser')
db_field = Group._meta.get_field('contact_email')
gr_admin = GroupAdmin(Group, AdminSite())
self.assertQuerysetEqual(self.admin.formfield_for_foreignkey(db_field, request).queryset,
gr_admin.formfield_for_foreignkey(db_field, request).queryset)
def test_filter_manytomany(self):
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
# if user has `members.list_global_member`, the filter returns all fields
request.user = User.objects.get(username='superuser')
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), request)
self.assertQuerysetEqual(field.queryset,
Member.objects.all(),
ordered=False)
# if not, it is filtered by permissions
u = User.objects.get(username='standard')
request.user = u
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), request)
self.assertQuerysetEqual(field.queryset,
u.member.filter_queryset_by_permissions(model=Member),
ordered=False)
# if no request is passed, no members are shown
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), None)
self.assertQuerysetEqual(field.queryset, Member.objects.none())
# if user has no associated member and does not have the special permission,
# the filter returns nothing
request.user = User.objects.get(username='foobar')
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), request)
self.assertQuerysetEqual(field.queryset, Member.objects.none(), ordered=False)
def test_filter_foreignkey(self):
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
# if user has `members.list_global_member`, the filter returns all fields
request.user = User.objects.get(username='superuser')
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), request)
self.assertQuerysetEqual(field.queryset,
Member.objects.all(),
ordered=False)
# if not, it is filtered by permissions
u = User.objects.get(username='standard')
request.user = u
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), request)
self.assertQuerysetEqual(field.queryset,
u.member.filter_queryset_by_permissions(model=Member),
ordered=False)
# if no request is passed, no members are shown
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), None)
self.assertQuerysetEqual(field.queryset, Member.objects.none())
# if user has no associated member and does not have the special permission,
# the filter returns nothing
request.user = User.objects.get(username='foobar')
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), request)
self.assertQuerysetEqual(field.queryset, Member.objects.none(), ordered=False)

Loading…
Cancel
Save