Merge remote-tracking branch 'origin/main' into MK/training_tab

pull/174/head
mariusrklein 4 months ago
commit f9de181f7f

@ -0,0 +1,12 @@
confirm_mail = """
Hiho custom test test {name},
du hast bei der JDAV %(SEKTION)s eine E-Mail Adresse hinterlegt. Da bei uns alle Kommunikation
per Email funktioniert, brauchen wir eine Bestätigung {whattoconfirm}.
Custom!
{link}
Test test
Deine JDAV test test %(SEKTION)s"""

@ -1,13 +1,18 @@
from django.test import TestCase from datetime import datetime, timedelta
from decimal import Decimal
from django.test import TestCase, RequestFactory
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib import admin from django.contrib import admin
from django.db import models from django.db import models
from django.test import RequestFactory from django.core.exceptions import ValidationError
from unittest.mock import Mock from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils.translation import gettext_lazy as _
from unittest.mock import Mock, patch
from rules.contrib.models import RulesModelMixin, RulesModelBase from rules.contrib.models import RulesModelMixin, RulesModelBase
from contrib.models import CommonModel from contrib.models import CommonModel
from contrib.rules import has_global_perm from contrib.rules import has_global_perm
from contrib.admin import CommonAdminMixin from contrib.admin import CommonAdminMixin
from utils import file_size_validator, RestrictedFileField, cvt_to_decimal, get_member, normalize_name, normalize_filename, coming_midnight, mondays_until_nth
User = get_user_model() User = get_user_model()
@ -91,3 +96,80 @@ class CommonAdminMixinTestCase(TestCase):
# Verify that the formfield_overrides were used # Verify that the formfield_overrides were used
self.assertIsNotNone(result) self.assertIsNotNone(result)
class UtilsTestCase(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpass123'
)
def test_file_size_validator_exceeds_limit(self):
"""Test file_size_validator when file exceeds size limit"""
validator = file_size_validator(1) # 1MB limit
# Create a mock file that exceeds the limit (2MB)
mock_file = Mock()
mock_file.size = 2 * 1024 * 1024 # 2MB
with self.assertRaises(ValidationError) as cm:
validator(mock_file)
# Check for the translated error message
expected_message = str(_('Please keep filesize under {} MiB. Current filesize: {:10.2f} MiB.').format(1, 2.00))
self.assertIn(expected_message, str(cm.exception))
def test_restricted_file_field_content_type_not_supported(self):
"""Test RestrictedFileField when content type is not supported"""
field = RestrictedFileField(content_types=['image/jpeg'])
# Create mock data with unsupported content type
mock_data = Mock()
mock_data.file = Mock()
mock_data.file.content_type = "text/plain"
# Mock the super().clean() to return our mock data
with patch.object(models.FileField, 'clean', return_value=mock_data):
with self.assertRaises(ValidationError) as cm:
field.clean("dummy")
# Check for the translated error message
expected_message = str(_('Filetype not supported.'))
self.assertIn(expected_message, str(cm.exception))
def test_restricted_file_field_size_exceeds_limit(self):
"""Test RestrictedFileField when file size exceeds limit"""
field = RestrictedFileField(max_upload_size=1) # 1 byte limit
# Create mock data with file that exceeds size limit
mock_data = Mock()
mock_data.file = Mock()
mock_data.file.content_type = "text/plain"
mock_data.file._size = 2 # 2 bytes, exceeds limit
# Mock the super().clean() to return our mock data
with patch.object(models.FileField, 'clean', return_value=mock_data):
with self.assertRaises(ValidationError) as cm:
field.clean("dummy")
# Check for the translated error message
expected_message = str(_('Please keep filesize under {}. Current filesize: {}').format(1, 2))
self.assertIn(expected_message, str(cm.exception))
def test_mondays_until_nth(self):
"""Test mondays_until_nth function"""
# Test with n=2 to get 3 Mondays (including the 0th)
result = mondays_until_nth(2)
# Should return a list of 3 dates
self.assertEqual(len(result), 3)
# All dates should be Mondays (weekday 0)
for date in result:
self.assertEqual(date.weekday(), 0) # Monday is 0
# Dates should be consecutive weeks
self.assertEqual(result[1] - result[0], timedelta(days=7))
self.assertEqual(result[2] - result[1], timedelta(days=7))

@ -25,7 +25,7 @@ if os.path.exists(os.path.join(CONFIG_DIR_PATH, TEXTS_FILE)):
with open(os.path.join(CONFIG_DIR_PATH, TEXTS_FILE), 'rb') as f: with open(os.path.join(CONFIG_DIR_PATH, TEXTS_FILE), 'rb') as f:
texts = tomli.load(f) texts = tomli.load(f)
else: else:
texts = {} texts = {} # pragma: no cover
def get_var(*keys, default='', dictionary=config): def get_var(*keys, default='', dictionary=config):

@ -38,13 +38,6 @@ class AdminTestCase(TestCase):
standard = create_custom_user('standard', ['Standard'], 'Paul', 'Wulter') standard = create_custom_user('standard', ['Standard'], 'Paul', 'Wulter')
trainer = create_custom_user('trainer', ['Standard', 'Trainings'], 'Lise', 'Lotte') trainer = create_custom_user('trainer', ['Standard', 'Trainings'], 'Lise', 'Lotte')
def _login(self, name):
c = Client()
res = c.login(username=name, password='secret')
# make sure we logged in
assert res
return c
def _add_middleware(self, request): def _add_middleware(self, request):
"""Add required middleware to request.""" """Add required middleware to request."""
# Session middleware # Session middleware

@ -2,3 +2,4 @@ from .basic import *
from .views import * from .views import *
from .tasks import * from .tasks import *
from .rules import * from .rules import *
from .templatetags import *

@ -0,0 +1,80 @@
from django.test import TestCase
from django.template import Context, Template
from datetime import datetime, date, timedelta
from members.templatetags.tex_extras import index, datetime_short, date_short, date_vs, time_short, add, plus
from members.templatetags.overview_extras import blToColor, render_bool
class TexExtrasTestCase(TestCase):
def setUp(self):
self.test_date = date(2024, 3, 15)
self.test_datetime = datetime(2024, 3, 15, 14, 30)
self.test_list = ['a', 'b', 'c']
def test_index_valid_position(self):
result = index(self.test_list, 1)
self.assertEqual(result, 'b')
def test_index_invalid_position(self):
result = index(self.test_list, 5)
self.assertEqual(result, '')
def test_index_type_error(self):
result = index(123, 1)
self.assertEqual(result, '')
def test_datetime_short(self):
result = datetime_short(self.test_datetime)
self.assertEqual(result, '15.03.2024 14:30')
def test_date_short(self):
result = date_short(self.test_date)
self.assertEqual(result, '15.03.24')
def test_date_vs(self):
result = date_vs(self.test_date)
self.assertEqual(result, '15.03.')
def test_time_short(self):
result = time_short(self.test_datetime)
self.assertEqual(result, '14:30')
def test_add_with_days(self):
result = add(self.test_date, 5)
self.assertEqual(result, date(2024, 3, 20))
def test_add_without_days(self):
result = add(self.test_date, None)
self.assertEqual(result, self.test_date)
def test_plus_with_second_number(self):
result = plus(10, 5)
self.assertEqual(result, 15)
def test_plus_without_second_number(self):
result = plus(10, None)
self.assertEqual(result, 10)
class OverviewExtrasTestCase(TestCase):
def test_blToColor_truthy_value(self):
result = blToColor(True)
self.assertEqual(result, 'green')
def test_blToColor_falsy_value(self):
result = blToColor(False)
self.assertEqual(result, 'red')
def test_render_bool_non_boolean_value(self):
with self.assertRaises(ValueError):
render_bool("not_a_boolean")
def test_render_bool_true(self):
result = render_bool(True)
self.assertIn('#bcd386', result)
self.assertIn('icon-tick', result)
def test_render_bool_false(self):
result = render_bool(False)
self.assertIn('#dba4a4', result)
self.assertIn('icon-cross', result)

@ -88,7 +88,7 @@ class Image(models.Model):
max_upload_size=10) max_upload_size=10)
def __str__(self): def __str__(self):
return os.path.basename(self.f.name) if self.f.name else _("Empty") return os.path.basename(self.f.name) if self.f.name else str(_("Empty"))
class Meta: class Meta:
verbose_name = _('image') verbose_name = _('image')

@ -1,16 +1,19 @@
from django.test import TestCase, Client import os
from django.urls import reverse from django.test import TestCase, Client, RequestFactory
from django.urls import reverse, NoReverseMatch
from django.conf import settings from django.conf import settings
from django.templatetags.static import static from django.templatetags.static import static
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from unittest import mock from unittest import mock
from importlib import reload from importlib import reload
from members.models import Member, Group, DIVERSE from members.models import Member, Group, DIVERSE
from startpage import urls from startpage import urls
from startpage.views import redirect, handler500
from .models import Post, Section, Image from .models import Post, Section, Image, Link, MemberOnPost
class BasicTestCase(TestCase): class BasicTestCase(TestCase):
@ -25,7 +28,7 @@ class BasicTestCase(TestCase):
file = SimpleUploadedFile("post_image.jpg", b"file_content", content_type="image/jpeg") file = SimpleUploadedFile("post_image.jpg", b"file_content", content_type="image/jpeg")
staff_post = Post.objects.create(title='Staff', urlname='staff', website_text='This is our staff: Peter.', staff_post = Post.objects.create(title='Staff', urlname='staff', website_text='This is our staff: Peter.',
section=orga) section=orga)
Image.objects.create(post=staff_post, f=file) self.image_with_file = Image.objects.create(post=staff_post, f=file)
file = SimpleUploadedFile("member_image.jpg", b"file_content", content_type="image/jpeg") file = SimpleUploadedFile("member_image.jpg", b"file_content", content_type="image/jpeg")
m = Member.objects.create(prename='crazy', lastname='cool', birth_date=timezone.now().date(), m = Member.objects.create(prename='crazy', lastname='cool', birth_date=timezone.now().date(),
email=settings.TEST_MAIL, gender=DIVERSE, email=settings.TEST_MAIL, gender=DIVERSE,
@ -39,6 +42,10 @@ class BasicTestCase(TestCase):
crazy_post.groups.add(crazy_group) crazy_post.groups.add(crazy_group)
crazy_post.save() crazy_post.save()
self.post_no_section = Post.objects.create(title='No Section', urlname='no-section', section=None)
self.image_no_file = Image.objects.create(post=staff_post)
self.test_link = Link.objects.create(title='Test Link', url='https://example.com')
class ModelsTestCase(BasicTestCase): class ModelsTestCase(BasicTestCase):
def test_str(self): def test_str(self):
@ -66,6 +73,41 @@ class ModelsTestCase(BasicTestCase):
'/de/{name}/last-trip'.format(name=settings.REPORTS_SECTION)) '/de/{name}/last-trip'.format(name=settings.REPORTS_SECTION))
self.assertEqual(post3.absolute_urlname(), reverse('startpage:post', args=(reports.urlname, 'last-trip'))) self.assertEqual(post3.absolute_urlname(), reverse('startpage:post', args=(reports.urlname, 'last-trip')))
def test_post_absolute_section_none(self):
"""Test Post.absolute_section when section is None"""
self.assertEqual(self.post_no_section.absolute_section(), 'Aktuelles')
def test_post_absolute_urlname_no_section(self):
"""Test Post.absolute_urlname when section is None"""
expected_url = reverse('startpage:post', args=('aktuelles', 'no-section'))
self.assertEqual(self.post_no_section.absolute_urlname(), expected_url)
def test_image_str_without_file(self):
"""Test Image.__str__ when no file is associated"""
self.assertEqual(str(self.image_no_file), str(_('Empty')))
def test_image_str_with_file(self):
"""Test Image.__str__ when file is associated"""
# The str should return basename of the file
expected = os.path.basename(self.image_with_file.f.name)
self.assertEqual(str(self.image_with_file), expected)
def test_link_str(self):
"""Test Link.__str__ method"""
self.assertEqual(str(self.test_link), 'Test Link')
def test_section_absolute_urlname_no_reverse_match(self):
"""Test Section.absolute_urlname when NoReverseMatch occurs"""
section = Section.objects.get(urlname='orga')
with mock.patch('startpage.models.reverse', side_effect=NoReverseMatch):
self.assertEqual(section.absolute_urlname(), str(_('deactivated')))
def test_post_absolute_urlname_no_reverse_match(self):
"""Test Post.absolute_urlname when NoReverseMatch occurs"""
post = Post.objects.get(urlname='staff')
with mock.patch('startpage.models.reverse', side_effect=NoReverseMatch):
self.assertEqual(post.absolute_urlname(), str(_('deactivated')))
class ViewTestCase(BasicTestCase): class ViewTestCase(BasicTestCase):
def test_index(self): def test_index(self):
@ -137,9 +179,7 @@ class ViewTestCase(BasicTestCase):
def test_post_image(self): def test_post_image(self):
c = Client() c = Client()
staff_post = Post.objects.get(urlname='staff') url = self.image_with_file.f.url
img = Image.objects.get(post=staff_post)
url = img.f.url
response = c.get('/de' + url) response = c.get('/de' + url)
self.assertEqual(response.status_code, 200, 'Images on posts should be visible without login.') self.assertEqual(response.status_code, 200, 'Images on posts should be visible without login.')
@ -155,3 +195,17 @@ class ViewTestCase(BasicTestCase):
url_names = [pattern.name for pattern in urls.urlpatterns if hasattr(pattern, 'name')] url_names = [pattern.name for pattern in urls.urlpatterns if hasattr(pattern, 'name')]
self.assertIn('index', url_names) self.assertIn('index', url_names)
self.assertEqual(len(urls.urlpatterns), 2) # Should have index and impressum only self.assertEqual(len(urls.urlpatterns), 2) # Should have index and impressum only
def test_redirect_view(self):
"""Test redirect view functionality"""
request = RequestFactory().get('/')
with mock.patch.object(settings, 'STARTPAGE_REDIRECT_URL', 'https://example.com'):
response = redirect(request)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, 'https://example.com')
def test_handler500(self):
"""Test custom 500 error handler"""
request = RequestFactory().get('/')
response = handler500(request)
self.assertEqual(response.status_code, 500)

Loading…
Cancel
Save