django-auditlog/auditlog_tests/test_render.py
mostafaeftekharizadeh 7d13fd4ba8
Add CustomLogEntry model support and update tests: (#764)
* Add CustomLogEntry model support and update tests:

- Added support for CustomLogEntry data model to extend django-auditlog capabilities

- Updated existing test cases to align with new model structure and data handling logic

- Added new test cases to validate CustomLogEntry behavior, model registration, and signal handling

- Ensured backward compatibility with existing LogEntry model where applicable

* Update auditlog/__init__.py

Co-authored-by: Youngkwang Yang <me@youngkwang.dev>

* run only one custom model test matrix (#761)

---------

Co-authored-by: Youngkwang Yang <me@youngkwang.dev>
2025-11-19 09:46:43 +01:00

167 lines
5.5 KiB
Python

from django.test import TestCase
from test_app.models import SimpleModel
from auditlog import get_logentry_model
from auditlog.templatetags.auditlog_tags import render_logentry_changes_html
LogEntry = get_logentry_model()
class RenderChangesTest(TestCase):
def _create_log_entry(self, action, changes):
return LogEntry.objects.log_create(
SimpleModel.objects.create(),
action=action,
changes=changes,
)
def test_render_changes_empty(self):
log_entry = self._create_log_entry(LogEntry.Action.CREATE, {})
result = render_logentry_changes_html(log_entry)
self.assertEqual(result, "")
def test_render_changes_simple_field(self):
changes = {"text": ["old text", "new text"]}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
self.assertIn("<table>", result)
self.assertIn("<th>#</th>", result)
self.assertIn("<th>Field</th>", result)
self.assertIn("<th>From</th>", result)
self.assertIn("<th>To</th>", result)
self.assertIn("old text", result)
self.assertIn("new text", result)
self.assertIsInstance(result, str)
def test_render_changes_password_field(self):
changes = {"password": ["oldpass", "newpass"]}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
self.assertIn("***", result)
self.assertNotIn("oldpass", result)
self.assertNotIn("newpass", result)
def test_render_changes_m2m_field(self):
changes = {
"related_objects": {
"type": "m2m",
"operation": "add",
"objects": ["obj1", "obj2", "obj3"],
}
}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
self.assertIn("<table>", result)
self.assertIn("<th>#</th>", result)
self.assertIn("<th>Relationship</th>", result)
self.assertIn("<th>Action</th>", result)
self.assertIn("<th>Objects</th>", result)
self.assertIn("add", result)
self.assertIn("obj1", result)
self.assertIn("obj2", result)
self.assertIn("obj3", result)
def test_render_changes_mixed_fields(self):
changes = {
"text": ["old text", "new text"],
"related_objects": {
"type": "m2m",
"operation": "remove",
"objects": ["obj1"],
},
}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
tables = result.count("<table>")
self.assertEqual(tables, 2)
self.assertIn("old text", result)
self.assertIn("new text", result)
self.assertIn("remove", result)
self.assertIn("obj1", result)
def test_render_changes_field_verbose_name(self):
changes = {"text": ["old", "new"]}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
self.assertIn("Text", result)
def test_render_changes_with_none_values(self):
changes = {"text": [None, "new text"], "boolean": [True, None]}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
self.assertIn("None", result)
self.assertIn("new text", result)
self.assertIn("True", result)
def test_render_changes_sorted_fields(self):
changes = {
"z_field": ["old", "new"],
"a_field": ["old", "new"],
"m_field": ["old", "new"],
}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
a_index = result.find("A field")
m_index = result.find("M field")
z_index = result.find("Z field")
self.assertLess(a_index, m_index)
self.assertLess(m_index, z_index)
def test_render_changes_m2m_sorted_fields(self):
changes = {
"z_related": {"type": "m2m", "operation": "add", "objects": ["obj1"]},
"a_related": {"type": "m2m", "operation": "remove", "objects": ["obj2"]},
}
log_entry = self._create_log_entry(LogEntry.Action.UPDATE, changes)
result = render_logentry_changes_html(log_entry)
a_index = result.find("A related")
z_index = result.find("Z related")
self.assertLess(a_index, z_index)
def test_render_changes_create_action(self):
changes = {
"text": [None, "new value"],
"boolean": [None, True],
}
log_entry = self._create_log_entry(LogEntry.Action.CREATE, changes)
result = render_logentry_changes_html(log_entry)
self.assertIn("<table>", result)
self.assertIn("new value", result)
self.assertIn("True", result)
def test_render_changes_delete_action(self):
changes = {
"text": ["old value", None],
"boolean": [True, None],
}
log_entry = self._create_log_entry(LogEntry.Action.DELETE, changes)
result = render_logentry_changes_html(log_entry)
self.assertIn("<table>", result)
self.assertIn("old value", result)
self.assertIn("True", result)
self.assertIn("None", result)