mirror of
https://github.com/jazzband/django-auditlog.git
synced 2026-03-16 22:20:26 +00:00
* 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>
167 lines
5.5 KiB
Python
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)
|