django-auditlog/src/testapp/tests.py

206 lines
7.5 KiB
Python
Raw Normal View History

2013-10-23 15:10:59 +00:00
import datetime
2014-03-14 16:15:31 +00:00
from django.contrib.auth.models import User, AnonymousUser
from django.core.exceptions import ValidationError
from django.db.models.signals import pre_save
from django.http import HttpResponse
from django.test import TestCase, RequestFactory
from auditlog.middleware import AuditlogMiddleware
2013-10-21 20:41:21 +00:00
from auditlog.models import LogEntry
from testapp.models import (SimpleModel, AltPrimaryKeyModel, ProxyModel,
SimpleIncludeModel, SimpleExcludeModel, AdditionDataIncludedModel,)
2013-10-23 15:10:59 +00:00
class SimpleModelTest(TestCase):
def setUp(self):
2013-10-23 15:10:59 +00:00
self.obj = SimpleModel.objects.create(text='I am not difficult.')
2013-10-21 20:41:21 +00:00
def test_create(self):
"""Creation is logged correctly."""
# Get the object to work with
2013-10-23 15:10:59 +00:00
obj = self.obj
2013-10-21 20:41:21 +00:00
# Check for log entries
self.assertTrue(obj.history.count() == 1, msg="There is one log entry")
try:
history = obj.history.get()
2013-10-23 15:10:59 +00:00
except obj.history.DoesNotExist:
2013-10-21 20:41:21 +00:00
self.assertTrue(False, "Log entry exists")
else:
self.assertEqual(history.action, LogEntry.Action.CREATE, msg="Action is 'CREATE'")
self.assertEqual(history.object_repr, str(obj), msg="Representation is equal")
def test_update(self):
"""Updates are logged correctly."""
# Get the object to work with
2013-10-23 15:10:59 +00:00
obj = self.obj
2013-10-21 20:41:21 +00:00
# Change something
obj.boolean = True
obj.save()
# Check for log entries
2013-10-21 20:41:21 +00:00
self.assertTrue(obj.history.filter(action=LogEntry.Action.UPDATE).count() == 1, msg="There is one log entry for 'UPDATE'")
history = obj.history.get(action=LogEntry.Action.UPDATE)
self.assertJSONEqual(history.changes, '{"boolean": ["False", "True"]}', msg="The change is correctly logged")
2013-10-23 15:10:59 +00:00
def test_delete(self):
"""Deletion is logged correctly."""
# Get the object to work with
obj = self.obj
history = obj.history.latest()
# Delete the object
obj.delete()
# Check for log entries
self.assertTrue(LogEntry.objects.filter(content_type=history.content_type, object_pk=history.object_pk, action=LogEntry.Action.DELETE).count() == 1, msg="There is one log entry for 'DELETE'")
def test_recreate(self):
SimpleModel.objects.all().delete()
self.setUp()
self.test_create()
class AltPrimaryKeyModelTest(SimpleModelTest):
def setUp(self):
self.obj = AltPrimaryKeyModel.objects.create(key=str(datetime.datetime.now()), text='I am strange.')
class ProxyModelTest(SimpleModelTest):
def setUp(self):
self.obj = ProxyModel.objects.create(text='I am not what you think.')
2014-03-14 16:15:31 +00:00
class MiddlewareTest(TestCase):
"""
Test the middleware responsible for connecting and disconnecting the signals used in automatic logging.
"""
def setUp(self):
self.middleware = AuditlogMiddleware()
self.factory = RequestFactory()
self.user = User.objects.create_user(username='test', email='test@example.com', password='top_secret')
2014-03-14 19:53:46 +00:00
def test_request_anonymous(self):
2014-03-14 16:15:31 +00:00
"""No actor will be logged when a user is not logged in."""
# Create a request
request = self.factory.get('/')
request.user = AnonymousUser()
# Run middleware
self.middleware.process_request(request)
# Validate result
self.assertFalse(pre_save.has_listeners(LogEntry))
2014-03-14 19:53:46 +00:00
# Finalize transaction
self.middleware.process_exception(request, None)
2014-03-14 16:15:31 +00:00
def test_request(self):
"""The actor will be logged when a user is logged in."""
# Create a request
request = self.factory.get('/')
request.user = self.user
# Run middleware
self.middleware.process_request(request)
# Validate result
self.assertTrue(pre_save.has_listeners(LogEntry))
2014-03-14 19:53:46 +00:00
# Finalize transaction
self.middleware.process_exception(request, None)
def test_response(self):
2014-03-14 16:15:31 +00:00
"""The signal will be disconnected when the request is processed."""
# Create a request
request = self.factory.get('/')
request.user = self.user
# Run middleware
self.middleware.process_request(request)
self.assertTrue(pre_save.has_listeners(LogEntry)) # The signal should be present before trying to disconnect it.
self.middleware.process_response(request, HttpResponse())
# Validate result
self.assertFalse(pre_save.has_listeners(LogEntry))
def test_exception(self):
"""The signal will be disconnected when an exception is raised."""
# Create a request
request = self.factory.get('/')
request.user = self.user
# Run middleware
self.middleware.process_request(request)
self.assertTrue(pre_save.has_listeners(LogEntry)) # The signal should be present before trying to disconnect it.
self.middleware.process_exception(request, ValidationError("Test"))
# Validate result
self.assertFalse(pre_save.has_listeners(LogEntry))
class SimpeIncludeModelTest(TestCase):
"""Log only changes in include_fields"""
def test_register_include_fields(self):
sim = SimpleIncludeModel(label='Include model', text='Looong text')
sim.save()
self.assertTrue(sim.history.count() == 1, msg="There is one log entry")
# Change label, record
sim.label = 'Changed label'
sim.save()
self.assertTrue(sim.history.count() == 2, msg="There are two log entries")
# Change text, ignore
sim.text = 'Short text'
sim.save()
self.assertTrue(sim.history.count() == 2, msg="There are two log entries")
class SimpeExcludeModelTest(TestCase):
"""Log only changes that are not in exclude_fields"""
def test_register_exclude_fields(self):
sem = SimpleIncludeModel(label='Exclude model', text='Looong text')
sem.save()
self.assertTrue(sem.history.count() == 1, msg="There is one log entry")
# Change label, ignore
sem.label = 'Changed label'
sem.save()
self.assertTrue(sem.history.count() == 2, msg="There are two log entries")
# Change text, record
sem.text = 'Short text'
sem.save()
self.assertTrue(sem.history.count() == 2, msg="There are two log entries")
class AdditionalDataModelTest(TestCase):
"""Log additional data if get_additional_data is defined in the model"""
def test_model_without_additional_data(self):
obj_wo_additional_data = SimpleModel.objects.create(text='No additional '
'data')
obj_log_entry = obj_wo_additional_data.history.get()
self.assertIsNone(obj_log_entry.additional_data)
def test_model_with_additional_data(self):
related_model = SimpleModel.objects.create(text='Log my reference')
obj_with_additional_data = AdditionDataIncludedModel(
label='Additional data to log entries', related=related_model)
obj_with_additional_data.save()
self.assertTrue(obj_with_additional_data.history.count() == 1,
msg="There is 1 log entry")
log_entry = obj_with_additional_data.history.get()
self.assertIsNotNone(log_entry.additional_data)
extra_data = log_entry.additional_data
self.assertTrue(extra_data['related_model_text'] == related_model.text,
msg="Related model's text is logged")
self.assertTrue(extra_data['related_model_id'] == related_model.id,
msg="Related model's id is logged")