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>
198 lines
7.1 KiB
Python
198 lines
7.1 KiB
Python
from django.test import TestCase, override_settings
|
|
from test_app.models import JSONModel, NullableFieldModel, RelatedModel, SimpleModel
|
|
|
|
from auditlog import get_logentry_model
|
|
from auditlog.registry import AuditlogModelRegistry
|
|
|
|
LogEntry = get_logentry_model()
|
|
|
|
|
|
class JSONForChangesTest(TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_auditlog = AuditlogModelRegistry()
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES="str")
|
|
def test_wrong_setting_type(self):
|
|
with self.assertRaisesMessage(
|
|
TypeError, "Setting 'AUDITLOG_STORE_JSON_CHANGES' must be a boolean"
|
|
):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_use_json_for_changes_with_simplemodel(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
smm = SimpleModel()
|
|
smm.save()
|
|
changes_dict = smm.history.latest().changes_dict
|
|
|
|
# compare the id, text, boolean and datetime fields
|
|
id_field_changes = changes_dict["id"]
|
|
self.assertIsNone(id_field_changes[0])
|
|
self.assertIsInstance(
|
|
id_field_changes[1], int
|
|
) # the id depends on state of the database
|
|
|
|
text_field_changes = changes_dict["text"]
|
|
self.assertEqual(text_field_changes, [None, ""])
|
|
|
|
boolean_field_changes = changes_dict["boolean"]
|
|
self.assertEqual(boolean_field_changes, [None, False])
|
|
|
|
# datetime should be serialized to string
|
|
datetime_field_changes = changes_dict["datetime"]
|
|
self.assertIsNone(datetime_field_changes[0])
|
|
self.assertIsInstance(datetime_field_changes[1], str)
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_use_json_for_changes_with_jsonmodel(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
json_model = JSONModel()
|
|
json_model.json = {"test_key": "test_value"}
|
|
json_model.save()
|
|
changes_dict = json_model.history.latest().changes_dict
|
|
|
|
id_field_changes = changes_dict["json"]
|
|
self.assertEqual(id_field_changes, [None, {"test_key": "test_value"}])
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_use_json_for_changes_with_jsonmodel_with_empty_list(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
json_model = JSONModel()
|
|
json_model.json = []
|
|
json_model.save()
|
|
changes_dict = json_model.history.latest().changes_dict
|
|
|
|
id_field_changes = changes_dict["json"]
|
|
self.assertEqual(id_field_changes, [None, []])
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_use_json_for_changes_with_jsonmodel_with_complex_data(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
json_model = JSONModel()
|
|
json_model.json = {
|
|
"key": "test_value",
|
|
"key_dict": {"inner_key": "inner_value"},
|
|
"key_tuple": ("item1", "item2", "item3"),
|
|
}
|
|
json_model.save()
|
|
changes_dict = json_model.history.latest().changes_dict
|
|
|
|
id_field_changes = changes_dict["json"]
|
|
self.assertEqual(
|
|
id_field_changes,
|
|
[
|
|
None,
|
|
{
|
|
"key": "test_value",
|
|
"key_dict": {"inner_key": "inner_value"},
|
|
"key_tuple": [
|
|
"item1",
|
|
"item2",
|
|
"item3",
|
|
], # tuple is converted to list, that's ok
|
|
},
|
|
],
|
|
)
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_use_json_for_changes_with_jsonmodel_with_related_model(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
simple = SimpleModel.objects.create()
|
|
one_simple = SimpleModel.objects.create()
|
|
related_model = RelatedModel.objects.create(
|
|
one_to_one=simple, related=one_simple
|
|
)
|
|
related_model.save()
|
|
changes_dict = related_model.history.latest().changes_dict
|
|
|
|
field_related_changes = changes_dict["related"]
|
|
self.assertEqual(field_related_changes, [None, one_simple.id])
|
|
|
|
field_one_to_one_changes = changes_dict["one_to_one"]
|
|
self.assertEqual(field_one_to_one_changes, [None, simple.id])
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_use_json_for_changes_update(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
simple = SimpleModel(text="original")
|
|
simple.save()
|
|
simple.text = "new"
|
|
simple.save()
|
|
|
|
changes_dict = simple.history.latest().changes_dict
|
|
|
|
text_changes = changes_dict["text"]
|
|
self.assertEqual(text_changes, ["original", "new"])
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_use_json_for_changes_delete(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
simple = SimpleModel()
|
|
simple.save()
|
|
simple.delete()
|
|
|
|
history = LogEntry.objects.all()
|
|
|
|
self.assertEqual(history.count(), 1, '"DELETE" record is always retained')
|
|
|
|
changes_dict = history.first().changes_dict
|
|
|
|
self.assertTrue(
|
|
all(v[1] is None for k, v in changes_dict.items()),
|
|
'all values in the changes dict should None, not "None"',
|
|
)
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=False)
|
|
def test_nullable_field_with_none_not_logged(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
obj = NullableFieldModel.objects.create(time=None, optional_text=None)
|
|
changes_dict = obj.history.latest().changes_dict
|
|
|
|
# None → None should NOT be logged as a change
|
|
self.assertNotIn("time", changes_dict)
|
|
self.assertNotIn("optional_text", changes_dict)
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=False)
|
|
def test_nullable_field_with_value_logged(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
obj = NullableFieldModel.objects.create(optional_text="something")
|
|
changes_dict = obj.history.latest().changes_dict
|
|
|
|
# None → "something" should be logged
|
|
self.assertIn("optional_text", changes_dict)
|
|
self.assertEqual(changes_dict["optional_text"], ["None", "something"])
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=True)
|
|
def test_nullable_field_with_none_not_logged_json_mode(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
obj = NullableFieldModel.objects.create(time=None, optional_text=None)
|
|
changes_dict = obj.history.latest().changes_dict
|
|
|
|
# None → None should NOT be logged
|
|
self.assertNotIn("time", changes_dict)
|
|
self.assertNotIn("optional_text", changes_dict)
|
|
|
|
@override_settings(AUDITLOG_STORE_JSON_CHANGES=False)
|
|
def test_nullable_field_update_none_to_value(self):
|
|
self.test_auditlog.register_from_settings()
|
|
|
|
obj = NullableFieldModel.objects.create(optional_text=None)
|
|
obj.optional_text = "updated"
|
|
obj.save()
|
|
|
|
changes_dict = obj.history.latest().changes_dict
|
|
|
|
# None → "updated" should be logged
|
|
self.assertIn("optional_text", changes_dict)
|
|
self.assertEqual(changes_dict["optional_text"], ["None", "updated"])
|