test_changelog.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. from django.contrib.contenttypes.models import ContentType
  2. from django.urls import reverse
  3. from rest_framework import status
  4. from dcim.choices import SiteStatusChoices
  5. from dcim.models import Site
  6. from extras.choices import *
  7. from extras.models import CustomField, CustomFieldValue, ObjectChange, Tag
  8. from utilities.testing import APITestCase
  9. from utilities.testing.utils import post_data
  10. from utilities.testing.views import ModelViewTestCase
  11. class ChangeLogViewTest(ModelViewTestCase):
  12. model = Site
  13. @classmethod
  14. def setUpTestData(cls):
  15. # Create a custom field on the Site model
  16. ct = ContentType.objects.get_for_model(Site)
  17. cf = CustomField(
  18. type=CustomFieldTypeChoices.TYPE_TEXT,
  19. name='my_field',
  20. required=False
  21. )
  22. cf.save()
  23. cf.obj_type.set([ct])
  24. def test_create_object(self):
  25. tags = self.create_tags('Tag 1', 'Tag 2')
  26. form_data = {
  27. 'name': 'Test Site 1',
  28. 'slug': 'test-site-1',
  29. 'status': SiteStatusChoices.STATUS_ACTIVE,
  30. 'cf_my_field': 'ABC',
  31. 'tags': [tag.pk for tag in tags],
  32. }
  33. request = {
  34. 'path': self._get_url('add'),
  35. 'data': post_data(form_data),
  36. }
  37. self.add_permissions('dcim.add_site', 'extras.view_tag')
  38. response = self.client.post(**request)
  39. self.assertHttpStatus(response, 302)
  40. site = Site.objects.get(name='Test Site 1')
  41. # First OC is the creation; second is the tags update
  42. oc_list = ObjectChange.objects.filter(
  43. changed_object_type=ContentType.objects.get_for_model(Site),
  44. changed_object_id=site.pk
  45. ).order_by('pk')
  46. self.assertEqual(oc_list[0].changed_object, site)
  47. self.assertEqual(oc_list[0].action, ObjectChangeActionChoices.ACTION_CREATE)
  48. self.assertEqual(oc_list[0].object_data['custom_fields']['my_field'], form_data['cf_my_field'])
  49. self.assertEqual(oc_list[1].action, ObjectChangeActionChoices.ACTION_UPDATE)
  50. self.assertEqual(oc_list[1].object_data['tags'], ['Tag 1', 'Tag 2'])
  51. def test_update_object(self):
  52. site = Site(name='Test Site 1', slug='test-site-1')
  53. site.save()
  54. tags = self.create_tags('Tag 1', 'Tag 2', 'Tag 3')
  55. site.tags.set('Tag 1', 'Tag 2')
  56. form_data = {
  57. 'name': 'Test Site X',
  58. 'slug': 'test-site-x',
  59. 'status': SiteStatusChoices.STATUS_PLANNED,
  60. 'cf_my_field': 'DEF',
  61. 'tags': [tags[2].pk],
  62. }
  63. request = {
  64. 'path': self._get_url('edit', instance=site),
  65. 'data': post_data(form_data),
  66. }
  67. self.add_permissions('dcim.change_site', 'extras.view_tag')
  68. response = self.client.post(**request)
  69. self.assertHttpStatus(response, 302)
  70. site.refresh_from_db()
  71. # Get only the most recent OC
  72. oc = ObjectChange.objects.filter(
  73. changed_object_type=ContentType.objects.get_for_model(Site),
  74. changed_object_id=site.pk
  75. ).first()
  76. self.assertEqual(oc.changed_object, site)
  77. self.assertEqual(oc.action, ObjectChangeActionChoices.ACTION_UPDATE)
  78. self.assertEqual(oc.object_data['custom_fields']['my_field'], form_data['cf_my_field'])
  79. self.assertEqual(oc.object_data['tags'], ['Tag 3'])
  80. def test_delete_object(self):
  81. site = Site(
  82. name='Test Site 1',
  83. slug='test-site-1'
  84. )
  85. site.save()
  86. self.create_tags('Tag 1', 'Tag 2')
  87. site.tags.set('Tag 1', 'Tag 2')
  88. CustomFieldValue.objects.create(
  89. field=CustomField.objects.get(name='my_field'),
  90. obj=site,
  91. value='ABC'
  92. )
  93. request = {
  94. 'path': self._get_url('delete', instance=site),
  95. 'data': post_data({'confirm': True}),
  96. }
  97. self.add_permissions('dcim.delete_site')
  98. response = self.client.post(**request)
  99. self.assertHttpStatus(response, 302)
  100. oc = ObjectChange.objects.first()
  101. self.assertEqual(oc.changed_object, None)
  102. self.assertEqual(oc.object_repr, site.name)
  103. self.assertEqual(oc.action, ObjectChangeActionChoices.ACTION_DELETE)
  104. self.assertEqual(oc.object_data['custom_fields']['my_field'], 'ABC')
  105. self.assertEqual(oc.object_data['tags'], ['Tag 1', 'Tag 2'])
  106. class ChangeLogAPITest(APITestCase):
  107. def setUp(self):
  108. super().setUp()
  109. # Create a custom field on the Site model
  110. ct = ContentType.objects.get_for_model(Site)
  111. cf = CustomField(
  112. type=CustomFieldTypeChoices.TYPE_TEXT,
  113. name='my_field',
  114. required=False
  115. )
  116. cf.save()
  117. cf.obj_type.set([ct])
  118. # Create some tags
  119. tags = (
  120. Tag(name='Tag 1', slug='tag-1'),
  121. Tag(name='Tag 2', slug='tag-2'),
  122. Tag(name='Tag 3', slug='tag-3'),
  123. )
  124. Tag.objects.bulk_create(tags)
  125. def test_create_object(self):
  126. data = {
  127. 'name': 'Test Site 1',
  128. 'slug': 'test-site-1',
  129. 'custom_fields': {
  130. 'my_field': 'ABC'
  131. },
  132. 'tags': [
  133. {'name': 'Tag 1'},
  134. {'name': 'Tag 2'},
  135. ]
  136. }
  137. self.assertEqual(ObjectChange.objects.count(), 0)
  138. url = reverse('dcim-api:site-list')
  139. self.add_permissions('dcim.add_site')
  140. response = self.client.post(url, data, format='json', **self.header)
  141. self.assertHttpStatus(response, status.HTTP_201_CREATED)
  142. site = Site.objects.get(pk=response.data['id'])
  143. # First OC is the creation; second is the tags update
  144. oc_list = ObjectChange.objects.filter(
  145. changed_object_type=ContentType.objects.get_for_model(Site),
  146. changed_object_id=site.pk
  147. ).order_by('pk')
  148. self.assertEqual(oc_list[0].changed_object, site)
  149. self.assertEqual(oc_list[0].action, ObjectChangeActionChoices.ACTION_CREATE)
  150. self.assertEqual(oc_list[0].object_data['custom_fields'], data['custom_fields'])
  151. self.assertEqual(oc_list[1].action, ObjectChangeActionChoices.ACTION_UPDATE)
  152. self.assertEqual(oc_list[1].object_data['tags'], ['Tag 1', 'Tag 2'])
  153. def test_update_object(self):
  154. site = Site(name='Test Site 1', slug='test-site-1')
  155. site.save()
  156. data = {
  157. 'name': 'Test Site X',
  158. 'slug': 'test-site-x',
  159. 'custom_fields': {
  160. 'my_field': 'DEF'
  161. },
  162. 'tags': [
  163. {'name': 'Tag 3'}
  164. ]
  165. }
  166. self.assertEqual(ObjectChange.objects.count(), 0)
  167. self.add_permissions('dcim.change_site')
  168. url = reverse('dcim-api:site-detail', kwargs={'pk': site.pk})
  169. response = self.client.put(url, data, format='json', **self.header)
  170. self.assertHttpStatus(response, status.HTTP_200_OK)
  171. site = Site.objects.get(pk=response.data['id'])
  172. # Get only the most recent OC
  173. oc = ObjectChange.objects.filter(
  174. changed_object_type=ContentType.objects.get_for_model(Site),
  175. changed_object_id=site.pk
  176. ).first()
  177. self.assertEqual(oc.changed_object, site)
  178. self.assertEqual(oc.action, ObjectChangeActionChoices.ACTION_UPDATE)
  179. self.assertEqual(oc.object_data['custom_fields'], data['custom_fields'])
  180. self.assertEqual(oc.object_data['tags'], ['Tag 3'])
  181. def test_delete_object(self):
  182. site = Site(
  183. name='Test Site 1',
  184. slug='test-site-1'
  185. )
  186. site.save()
  187. site.tags.set(*Tag.objects.all()[:2])
  188. CustomFieldValue.objects.create(
  189. field=CustomField.objects.get(name='my_field'),
  190. obj=site,
  191. value='ABC'
  192. )
  193. self.assertEqual(ObjectChange.objects.count(), 0)
  194. self.add_permissions('dcim.delete_site')
  195. url = reverse('dcim-api:site-detail', kwargs={'pk': site.pk})
  196. response = self.client.delete(url, **self.header)
  197. self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
  198. self.assertEqual(Site.objects.count(), 0)
  199. oc = ObjectChange.objects.first()
  200. self.assertEqual(oc.changed_object, None)
  201. self.assertEqual(oc.object_repr, site.name)
  202. self.assertEqual(oc.action, ObjectChangeActionChoices.ACTION_DELETE)
  203. self.assertEqual(oc.object_data['custom_fields'], {'my_field': 'ABC'})
  204. self.assertEqual(oc.object_data['tags'], ['Tag 1', 'Tag 2'])