Source code for notifications.tests.test_models

"""Tests for the NotificationModel model and related functionality in the notifications app."""

import pytest
from devices.models import DeviceModel
from django.utils import timezone
from pki.models import DomainModel, IssuingCaModel

from notifications.models import (
    NotificationConfig,
    NotificationMessageModel,
    NotificationModel,
    NotificationStatus,
)

[docs] DEFAULT_EXPIRY_WARNING_DAYS = 30
[docs] DEFAULT_RSA_KEY_SIZE = 2048
[docs] EXPECTED_STATUS_COUNT = 2
@pytest.mark.django_db
[docs] def test_create_notification_with_issuing_ca( test_message: NotificationMessageModel, test_status: NotificationStatus, setup_test_issuing_ca: IssuingCaModel) -> None: """Test creation of a NotificationModel linked to an Issuing CA.""" notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.WARNING, notification_source=NotificationModel.NotificationSource.ISSUING_CA, message_type=NotificationModel.NotificationMessageType.CUSTOM, message=test_message, issuing_ca=setup_test_issuing_ca, ) notification.statuses.set([test_status]) assert notification.issuing_ca == setup_test_issuing_ca assert notification.short_translated == 'Test short' assert notification.long_translated == 'Test long description' assert str(notification).startswith('WARNING - Test short')
@pytest.mark.django_db
[docs] def test_create_notification_with_domain( test_message: NotificationMessageModel, test_status: NotificationStatus, test_domain: DomainModel) -> None: """Test creation of a NotificationModel linked to a domain.""" notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.INFO, notification_source=NotificationModel.NotificationSource.DOMAIN, message_type=NotificationModel.NotificationMessageType.CUSTOM, message=test_message, domain=test_domain, ) notification.statuses.set([test_status]) assert notification.domain == test_domain assert notification.short_translated == 'Test short' assert notification.long_translated == 'Test long description'
@pytest.mark.django_db
[docs] def test_notification_translations_for_builtins(test_status: NotificationStatus) -> None : """Test translated messages for built-in (non-CUSTOM) notification types.""" notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.CRITICAL, notification_source=NotificationModel.NotificationSource.SYSTEM, message_type=NotificationModel.NotificationMessageType.SYSTEM_NOT_HEALTHY, message_data={}, ) notification.statuses.set([test_status]) assert 'System health check failed' in notification.short_translated assert 'The system health check detected an issue' in notification.long_translated
@pytest.mark.django_db
[docs] def test_unknown_message_type_fallback(test_status: NotificationStatus) -> None: """Test fallback behavior when an unknown message_type is provided.""" notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.CRITICAL, notification_source=NotificationModel.NotificationSource.SYSTEM, message_type='UNKNOWN_CODE', message_data={}, ) notification.statuses.set([test_status]) assert 'Unknown Notification message type.' in notification.short_translated assert 'Guess we messed up' in notification.long_translated
@pytest.mark.django_db
[docs] def test_notification_with_multiple_statuses(test_message: NotificationMessageModel, test_domain: DomainModel) -> None: """Test that multiple statuses can be added to a NotificationModel.""" status_new = NotificationStatus.objects.create(status=NotificationStatus.StatusChoices.NEW) status_ack = NotificationStatus.objects.create(status=NotificationStatus.StatusChoices.ACKNOWLEDGED) notif = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.INFO, notification_source=NotificationModel.NotificationSource.DOMAIN, message_type=NotificationModel.NotificationMessageType.CUSTOM, message=test_message, domain=test_domain, ) notif.statuses.set([status_new, status_ack]) statuses = notif.statuses.all() assert statuses.count() == EXPECTED_STATUS_COUNT assert status_new in statuses assert status_ack in statuses
@pytest.mark.django_db
[docs] def test_notification_str_fallback_missing_message(test_domain: DomainModel) -> None: """Test that __str__ handles missing message (should not raise).""" notif = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.CRITICAL, notification_source=NotificationModel.NotificationSource.DOMAIN, message_type=NotificationModel.NotificationMessageType.CUSTOM, domain=test_domain, message=None, # required=False on model level ) assert str(notif) == f'{notif.get_notification_type_display()} - No message'
@pytest.mark.django_db
[docs] def test_notification_str_with_long_message(test_domain: DomainModel) -> None: """Test that __str__ properly truncates long messages to 20 characters.""" message = NotificationMessageModel.objects.create( short_description='This is a very long message that should be truncated', long_description='Full description' ) notif = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.INFO, notification_source=NotificationModel.NotificationSource.DOMAIN, message_type=NotificationModel.NotificationMessageType.CUSTOM, domain=test_domain, message=message, ) assert str(notif) == f'{notif.get_notification_type_display()} - This is a very long '
@pytest.mark.django_db
[docs] def test_notification_str_with_empty_message(test_domain: DomainModel) -> None: """Test that __str__ handles empty message description properly.""" message = NotificationMessageModel.objects.create( short_description='', long_description='Some long description' ) notif = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.WARNING, notification_source=NotificationModel.NotificationSource.DOMAIN, message_type=NotificationModel.NotificationMessageType.CUSTOM, domain=test_domain, message=message, ) assert str(notif) == f'{notif.get_notification_type_display()} - '
@pytest.mark.django_db
[docs] def test_notification_str_with_special_characters(test_domain: DomainModel) -> None: """Test that __str__ handles messages with special characters properly.""" message = NotificationMessageModel.objects.create( short_description='!@#$%^&*()_+-=[]{}', long_description='Test with special characters' ) notif = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.CRITICAL, notification_source=NotificationModel.NotificationSource.DOMAIN, message_type=NotificationModel.NotificationMessageType.CUSTOM, domain=test_domain, message=message, ) assert str(notif) == f'{notif.get_notification_type_display()} - !@#$%^&*()_+-=[]{{}}'
@pytest.mark.django_db
[docs] def test_notification_for_issuing_ca_creation( test_message: NotificationMessageModel, test_status: NotificationStatus, setup_test_issuing_ca: IssuingCaModel) -> None: """Test notification creation when a new issuing CA is created.""" notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.INFO, notification_source=NotificationModel.NotificationSource.ISSUING_CA, message_type=NotificationModel.NotificationMessageType.CUSTOM, message=test_message, issuing_ca=setup_test_issuing_ca, message_data={ 'ca_name': setup_test_issuing_ca.unique_name, 'ca_type': str(setup_test_issuing_ca.IssuingCaTypeChoice(setup_test_issuing_ca.issuing_ca_type).label), 'common_name': setup_test_issuing_ca.common_name } ) notification.statuses.set([test_status]) assert notification.issuing_ca == setup_test_issuing_ca assert notification.message_data['ca_name'] == setup_test_issuing_ca.unique_name
@pytest.mark.django_db
[docs] def test_create_notification_with_device( test_message: NotificationMessageModel, test_status: NotificationStatus, test_device: DeviceModel ) -> None: """Test creation of a NotificationModel linked to a device.""" notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.WARNING, notification_source=NotificationModel.NotificationSource.DEVICE, message_type=NotificationModel.NotificationMessageType.CUSTOM, message=test_message, device=test_device, ) notification.statuses.set([test_status]) assert notification.device == test_device assert notification.short_translated == 'Test short' assert notification.long_translated == 'Test long description'
@pytest.mark.django_db
[docs] def test_notification_config_defaults() -> None: """Test NotificationConfig default values and singleton behavior.""" config = NotificationConfig.get() assert config.cert_expiry_warning_days == DEFAULT_EXPIRY_WARNING_DAYS assert config.issuing_ca_expiry_warning_days == DEFAULT_EXPIRY_WARNING_DAYS assert config.rsa_minimum_key_size == DEFAULT_RSA_KEY_SIZE config2 = NotificationConfig.get() assert config == config2
@pytest.mark.django_db
[docs] def test_notification_created_at_auto_now() -> None: """Test that created_at is automatically set when creating a notification.""" before_creation = timezone.now() notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.INFO, notification_source=NotificationModel.NotificationSource.SYSTEM, message_type=NotificationModel.NotificationMessageType.SYSTEM_NOT_HEALTHY ) after_creation = timezone.now() assert before_creation <= notification.created_at <= after_creation
@pytest.mark.django_db
[docs] def test_notification_event_filtering() -> None: """Test that notifications can be filtered by event.""" NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.WARNING, notification_source=NotificationModel.NotificationSource.SYSTEM, message_type=NotificationModel.NotificationMessageType.SYSTEM_NOT_HEALTHY, event='test_event' ) found = NotificationModel.objects.filter(event='test_event').exists() assert found assert NotificationModel.objects.filter(event='non_existent').exists() is False
@pytest.mark.django_db
[docs] def test_custom_message_with_empty_descriptions() -> None: """Test custom notification message with empty descriptions.""" message = NotificationMessageModel.objects.create( short_description='', long_description='' ) notification = NotificationModel.objects.create( notification_type=NotificationModel.NotificationTypes.INFO, notification_source=NotificationModel.NotificationSource.SYSTEM, message_type=NotificationModel.NotificationMessageType.CUSTOM, message=message ) assert notification.short_translated == '' assert notification.long_translated == ''