|
|
|
@ -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))
|
|
|
|
|