Coverage for website/registrations/tests/test_models.py: 100.00%
256 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1from django.contrib.auth import get_user_model
2from django.core.exceptions import ValidationError
3from django.test import TestCase, override_settings
4from django.utils import timezone
5from django.utils.translation import gettext_lazy as _
7from freezegun import freeze_time
9from members.models import Member, Membership, Profile
10from registrations import payables
11from registrations.models import Entry, Reference, Registration, Renewal
14@override_settings(SUSPEND_SIGNALS=True)
15class EntryTest(TestCase):
16 fixtures = ["members.json"]
18 @classmethod
19 def setUpTestData(cls):
20 cls.registration = Registration.objects.create(
21 first_name="John",
22 last_name="Doe",
23 email="johndoe@example.com",
24 programme="computingscience",
25 starting_year=2014,
26 address_street="Heyendaalseweg 135",
27 address_street2="",
28 address_postal_code="6525AJ",
29 address_city="Nijmegen",
30 address_country="NL",
31 phone_number="06123456789",
32 birthday=timezone.now().replace(year=1990),
33 length=Entry.MEMBERSHIP_YEAR,
34 membership_type=Membership.MEMBER,
35 status=Entry.STATUS_CONFIRM,
36 )
37 cls.member = Member.objects.filter(last_name="Wiggers").first()
38 cls.renewal = Renewal(
39 member=cls.member,
40 length=Entry.MEMBERSHIP_STUDY,
41 membership_type=Membership.MEMBER,
42 )
44 def setUp(self) -> None:
45 payables.register()
47 def test_str(self):
48 entry = Entry(registration=self.registration)
49 self.assertEqual(
50 str(entry),
51 "{} {} ({})".format( # noqa: UP032
52 self.registration.first_name,
53 self.registration.last_name,
54 self.registration.email,
55 ),
56 )
58 entry = Entry(renewal=self.renewal)
59 self.assertEqual(
60 str(entry),
61 f"{self.member.first_name} {self.member.last_name} ({self.member.email})",
62 )
64 @freeze_time("2019-01-01")
65 def test_save(self):
66 entry = Entry(length=Entry.MEMBERSHIP_YEAR, registration=self.registration)
68 entry.status = Entry.STATUS_ACCEPTED
69 test_value = timezone.now().replace(year=1996)
70 entry.updated_at = test_value
72 with self.subTest("Accepted should not update `updated_at`"):
73 entry.save()
74 self.assertEqual(entry.updated_at, test_value)
76 entry.status = Entry.STATUS_REJECTED
78 with self.subTest("Rejected should not update `updated_at`"):
79 entry.save()
80 self.assertEqual(entry.updated_at, test_value)
82 entry.status = Entry.STATUS_REVIEW
84 with self.subTest("Review should update `updated_at`"):
85 entry.save()
86 self.assertNotEqual(entry.updated_at, test_value)
88 entry.length = Entry.MEMBERSHIP_STUDY
90 with self.subTest("Type `Member` should not change length"):
91 entry.save()
92 self.assertEqual(entry.length, Entry.MEMBERSHIP_STUDY)
94 entry.membership_type = Membership.BENEFACTOR
96 def test_clean(self):
97 entry = Entry(registration=self.registration)
99 entry.contribution = None
100 entry.length = Entry.MEMBERSHIP_YEAR
101 entry.membership_type = Membership.BENEFACTOR
103 with self.subTest("Type `Benefactor` should require contribution"):
104 with self.assertRaises(ValidationError):
105 entry.clean()
106 entry.contribution = 7.5
107 entry.clean()
109 with self.subTest("Type `Benefactor` should require year length"):
110 entry.length = Entry.MEMBERSHIP_STUDY
111 with self.assertRaises(ValidationError):
112 entry.clean()
115@override_settings(SUSPEND_SIGNALS=True)
116@freeze_time("2019-01-01")
117class RegistrationTest(TestCase):
118 """Tests registrations."""
120 @classmethod
121 def setUpTestData(cls):
122 cls.registration = Registration.objects.create(
123 first_name="John",
124 last_name="Doe",
125 email="johndoe@example.com",
126 programme="computingscience",
127 starting_year=2014,
128 address_street="Heyendaalseweg 135",
129 address_street2="",
130 address_postal_code="6525AJ",
131 address_city="Nijmegen",
132 address_country="NL",
133 phone_number="06123456789",
134 student_number="s1234567",
135 birthday=timezone.now().replace(year=1990),
136 length=Entry.MEMBERSHIP_YEAR,
137 membership_type=Membership.MEMBER,
138 status=Entry.STATUS_CONFIRM,
139 contribution=7.5,
140 )
142 def setUp(self):
143 self.registration.refresh_from_db()
145 def test_str(self):
146 self.assertEqual(
147 str(self.registration),
148 "{} {} ({})".format( # noqa: UP032
149 self.registration.first_name,
150 self.registration.last_name,
151 self.registration.email,
152 ),
153 )
155 def test_get_full_name(self):
156 self.assertEqual(
157 self.registration.get_full_name(),
158 f"{self.registration.first_name} {self.registration.last_name}",
159 )
161 def test_full_clean_works(self):
162 self.registration.full_clean()
164 def test_clean_works(self):
165 self.registration.clean()
167 def test_unique_email_user(self):
168 self.registration.clean()
169 user = get_user_model().objects.create_user("johnnydoe", "johndoe@example.com")
171 with self.assertRaises(ValidationError):
172 self.registration.clean()
174 user.delete()
175 self.registration.clean()
176 Registration.objects.create(
177 length=Entry.MEMBERSHIP_YEAR,
178 first_name="John",
179 last_name="Doe",
180 birthday=timezone.now().replace(year=1990),
181 email="johndoe@example.com",
182 )
184 with self.assertRaises(ValidationError):
185 self.registration.clean()
187 def test_require_past_birthday(self):
188 registration = Registration.objects.create(
189 length=Entry.MEMBERSHIP_YEAR,
190 first_name="John",
191 last_name="Doe",
192 birthday=timezone.now().date() + timezone.timedelta(weeks=52),
193 )
195 with self.assertRaises(ValidationError):
196 registration.clean()
198 def test_unique_student_number_user(self):
199 self.registration.student_number = "s1234567"
200 self.registration.clean()
202 user = get_user_model().objects.create_user("johnnydoe", "johndoe2@example.com")
203 Profile.objects.create(user=user, student_number="s1234567")
205 with self.assertRaises(ValidationError):
206 self.registration.clean()
208 user.delete()
209 self.registration.clean()
210 Registration.objects.create(
211 length=Entry.MEMBERSHIP_YEAR,
212 first_name="John",
213 last_name="Doe",
214 birthday=timezone.now().replace(year=1990),
215 student_number="s1234567",
216 )
218 with self.assertRaises(ValidationError):
219 self.registration.clean()
221 def test_require_student_number_members(self):
222 with self.subTest("No student number entered"):
223 self.registration.student_number = None
224 with self.assertRaisesMessage(
225 ValidationError, "{'student_number': ['This field is required.']}"
226 ):
227 self.registration.clean()
229 with self.subTest("Type is benefactor"):
230 self.registration.student_number = None
231 self.registration.membership_type = Membership.BENEFACTOR
232 self.registration.contribution = 7.5
233 self.registration.clean()
235 def test_unique_username_user(self):
236 self.registration.username = "johndoe"
237 self.registration.clean()
239 get_user_model().objects.create_user("johndoe", "johndoe@example.com")
241 with self.assertRaises(ValidationError):
242 self.registration.clean()
244 def test_require_programme_members(self):
245 self.registration.programme = None
246 with self.assertRaisesMessage(
247 ValidationError, "{'programme': ['This field is required.']}"
248 ):
249 self.registration.clean()
250 self.registration.membership_type = Membership.BENEFACTOR
251 self.registration.contribution = 7.5
252 self.registration.clean()
254 def test_require_starting_year_members(self):
255 self.registration.starting_year = None
256 with self.assertRaisesMessage(
257 ValidationError, "{'starting_year': ['This field is required.']}"
258 ):
259 self.registration.clean()
260 self.registration.membership_type = Membership.BENEFACTOR
261 self.registration.contribution = 7.5
262 self.registration.clean()
264 def test_require_bank_details(self):
265 self.registration.direct_debit = True
267 with self.assertRaises(ValidationError):
268 self.registration.clean()
270 self.registration.iban = "BE91ABNA0417164300"
272 with self.assertRaises(ValidationError):
273 self.registration.clean()
275 self.registration.initials = "J"
277 with self.assertRaises(ValidationError):
278 self.registration.clean()
280 self.registration.signature = "base64,png"
282 with self.assertRaises(ValidationError):
283 self.registration.clean()
285 self.registration.bic = "ADSGBEBZ"
287 self.registration.clean()
289 def test_generate_default_username(self):
290 registration = Registration(first_name="John", last_name="Doe")
292 self.assertEqual(registration._generate_default_username(), "jdoe")
294 registration.last_name = (
295 "famgtjbblvpcxpebclsjfamgtjbblvpcxpebcl"
296 "sjfamgtjbblvpcxpebclsjfamgtjbblvpcxpeb"
297 "clsjfamgtjbblvpcxpebclsjfamgtjbblvpcxp"
298 "ebclsjfamgtjbblvpcxpebclsjfamgtjbblvpc"
299 "xpebclsj"
300 )
302 self.assertEqual(
303 registration._generate_default_username(),
304 "jfamgtjbblvpcxpebclsjfamgtjbblvpcxpebclsjf"
305 "amgtjbblvpcxpebclsjfamgtjbblvpcxpebclsjfam"
306 "gtjbblvpcxpebclsjfamgtjbblvpcxpebclsjfamgt"
307 "jbblvpcxpebclsjfamgtjbbl",
308 )
310 possibilities = [
311 ("Bram", "in 't Zandt", "bintzandt"),
312 ("Astrid", "van der Jagt", "avanderjagt"),
313 ("Bart", "van den Boom", "bvandenboom"),
314 ("Richard", "van Ginkel", "rvanginkel"),
315 ("Edwin", "de Koning", "edekoning"),
316 ("Martijn", "de la Cosine", "mdelacosine"),
317 ("Robert", "Hissink Muller", "rhissinkmuller"),
318 ("Robert", "Al-Malak", "ralmalak"),
319 ("Arthur", "Domelé", "adomele"),
320 ("Ben", "Brücker", "bbrucker"),
321 ]
323 for first_name, last_name, username in possibilities:
324 (registration._generate_default_username(),)
325 self.assertEqual(
326 Registration(
327 first_name=first_name, last_name=last_name
328 )._generate_default_username(),
329 username,
330 )
332 def test_get_username(self):
333 self.assertEqual(
334 Registration(first_name="John", last_name="Doe").get_username(),
335 "jdoe",
336 )
337 self.assertEqual(
338 Registration(
339 first_name="John", last_name="Doe", username="johnny"
340 ).get_username(),
341 "johnny",
342 )
344 def test_check_user_is_unique(self):
345 user = get_user_model().objects.create_user(
346 "johnnydoe", "johnnydoe@example.com"
347 )
349 registration = Registration.objects.create(
350 first_name="John",
351 last_name="Doe",
352 email="johndoe@example.com",
353 programme="computingscience",
354 student_number="s1234567",
355 starting_year=2014,
356 address_street="Heyendaalseweg 135",
357 address_street2="",
358 address_postal_code="6525AJ",
359 address_city="Nijmegen",
360 address_country="NL",
361 phone_number="06123456789",
362 birthday=timezone.now().replace(year=1990, day=1).date(),
363 length=Entry.MEMBERSHIP_YEAR,
364 contribution=7.5,
365 membership_type=Membership.MEMBER,
366 status=Entry.STATUS_CONFIRM,
367 )
369 self.assertEqual(registration.check_user_is_unique(), True)
371 user.username = "jdoe"
372 user.save()
374 self.assertEqual(registration.check_user_is_unique(), False)
376 user.username = "johnnydoe"
377 user.email = "johndoe@example.com"
378 user.save()
380 self.assertEqual(registration.check_user_is_unique(), False)
382 user.username = "jdoe"
383 user.email = "unique@example.com"
384 user.save()
386 registration.username = "unique_username"
388 self.assertEqual(registration.check_user_is_unique(), True)
390 def test_foreign_bankaccount_without_bic(self):
391 self.registration.initials = "J"
392 self.registration.signature = "base64,png"
393 self.registration.iban = "XX91ABNA0123456789"
394 self.registration.bic = ""
395 self.registration.clean()
398@override_settings(SUSPEND_SIGNALS=True)
399@freeze_time("2019-01-01")
400class RenewalTest(TestCase):
401 fixtures = ["members.json"]
403 def setUp(self):
404 self.member = Member.objects.filter(last_name="Wiggers").first()
405 self.renewal = Renewal(
406 member=self.member,
407 length=Entry.MEMBERSHIP_STUDY,
408 contribution=8,
409 membership_type=Membership.MEMBER,
410 )
412 def test_str(self):
413 self.assertEqual(
414 str(self.renewal),
415 f"{self.member.first_name} {self.member.last_name} ({self.member.email})",
416 )
418 def test_save(self):
419 self.renewal.pk = 2
420 self.renewal.status = Entry.STATUS_ACCEPTED
421 self.renewal.save()
423 self.assertEqual(self.renewal.status, Entry.STATUS_ACCEPTED)
425 self.renewal.pk = None
426 self.renewal.save()
428 self.assertEqual(self.renewal.status, Entry.STATUS_REVIEW)
430 def test_clean_works(self):
431 self.member.membership_set.all().delete()
432 self.renewal.clean()
434 def test_existing_renewal_in_review(self):
435 Renewal.objects.create(
436 member=self.member,
437 length=Entry.MEMBERSHIP_STUDY,
438 membership_type=Membership.MEMBER,
439 )
441 with self.assertRaises(ValidationError):
442 self.renewal.clean()
444 try:
445 self.renewal.clean()
446 except ValidationError as e:
447 self.assertEqual(
448 e.message, _("You already have a renewal request queued for review.")
449 )
451 def test_not_within_renew_period(self):
452 membership = self.member.latest_membership
453 membership.until = timezone.now().date() + timezone.timedelta(days=32)
454 membership.save()
456 self.renewal.length = Entry.MEMBERSHIP_YEAR
458 with self.assertRaises(ValidationError):
459 self.renewal.clean()
461 try:
462 self.renewal.clean()
463 except ValidationError as e:
464 self.assertCountEqual(
465 e.error_dict,
466 {
467 "length": "You cannot renew your membership at this moment.",
468 },
469 )
471 def test_within_renew_period(self):
472 self.renewal.length = Entry.MEMBERSHIP_YEAR
474 membership = self.member.latest_membership
475 membership.until = timezone.now().date() + timezone.timedelta(days=31)
476 membership.save()
478 self.renewal.clean()
480 def test_benefactor_no_study_length(self):
481 self.renewal.length = Entry.MEMBERSHIP_STUDY
482 self.renewal.membership_type = Membership.BENEFACTOR
483 membership = self.member.latest_membership
484 membership.until = timezone.now().date()
485 membership.save()
487 with self.assertRaises(ValidationError):
488 self.renewal.clean()
490 try:
491 self.renewal.clean()
492 except ValidationError as e:
493 self.assertCountEqual(
494 e.error_dict,
495 {
496 "length": "Benefactors cannot have a membership "
497 "that lasts their entire study duration.",
498 },
499 )
501 def test_has_active_membership(self):
502 membership = self.member.current_membership
503 membership.until = None
504 membership.save()
506 with self.assertRaises(ValidationError):
507 self.renewal.clean()
509 try:
510 self.renewal.clean()
511 except ValidationError as e:
512 self.assertCountEqual(
513 e.error_dict,
514 {
515 "length": "You currently have an active membership.",
516 "membership_type": "You currently have an active membership.",
517 },
518 )
521@override_settings(SUSPEND_SIGNALS=True)
522class ReferenceTest(TestCase):
523 fixtures = ["members.json"]
525 def test_str(self):
526 member = Member.objects.filter(last_name="Wiggers").first()
527 renewal = Renewal(
528 member=member,
529 length=Entry.MEMBERSHIP_YEAR,
530 membership_type=Membership.MEMBER,
531 )
533 ref = Reference(member=member, entry=renewal)
534 self.assertEqual(
535 str(ref), "Reference from Thom Wiggers (thom) for Thom Wiggers ()"
536 )