loko/loko/interventions/tests/test_calendar_notes_docs.py

234 lines
9 KiB
Python

import json
from unittest import mock
from datetime import datetime
from django.test import SimpleTestCase, RequestFactory
from django.contrib.auth.models import AnonymousUser
from django.urls import reverse
from django.utils import timezone
from interventions.views.calendar import intervention_calendar_details_ajax
from interventions.models import InterventionNote
class DummyConfig:
regional_standard = 'FR'
linked_configs = mock.MagicMock(values_list=lambda *args, **kwargs: [])
class DummyUser:
def __init__(self, id=1, first_name="Jean", last_name="Dupont"):
self.id = id
self.pk = id
self.first_name = first_name
self.last_name = last_name
self.is_authenticated = True
self.config = DummyConfig()
def get_full_name(self):
return f"{self.first_name} {self.last_name}"
def __str__(self):
return self.get_full_name()
class DummyNote:
def __init__(self, id, note_type, type_display, badge_class, icon_class, content, note_time, note_author, updated_at=None, updated_by=None):
self.id = id
self.pk = id
self.note_type = note_type
self._type_display = type_display
self.type_badge_class = badge_class
self.type_icon_class = icon_class
self.content = content
self.note_time = note_time
self.note_author = note_author
self.updated_at = updated_at
self.updated_by = updated_by
def get_note_type_display(self):
return self._type_display
class DummyDoc:
def __init__(self, id, filename, thumbnail_path=None, upload_date=None, uploaded_by=None):
self.id = id
self.pk = id
self.filename = filename
self.upload_date = upload_date or timezone.now()
self.uploaded_by = uploaded_by
self.file = type('DummyFile', (), {'name': filename})()
if thumbnail_path:
self.thumbnail = type('DummyThumb', (), {'name': thumbnail_path})()
else:
self.thumbnail = None
self._meta = type('DummyMeta', (), {
'app_label': 'interventions',
'model_name': 'interventiondocument',
'object_name': 'InterventionDocument',
})()
class CalendarInterventionDetailsAjaxSimpleTests(SimpleTestCase):
databases = set()
def setUp(self):
self.factory = RequestFactory()
self.url = reverse('interventions:intervention_calendar_details_ajax', args=[123])
def _create_request(self, user=None):
request = self.factory.get(self.url)
request.user = user if user is not None else AnonymousUser()
request.session = {
'account_switch_allowed_user_ids': [getattr(request.user, 'pk', 1)],
'account_switch_origin_user_id': getattr(request.user, 'pk', 1),
}
return request
def test_url_resolves(self):
self.assertEqual(self.url, '/interventions/calendar/intervention/123/details/')
def test_anonymous_user_redirects_to_login(self):
request = self._create_request(AnonymousUser())
response = intervention_calendar_details_ajax(request, intervention_id=123)
self.assertEqual(response.status_code, 302)
self.assertIn('/accounts/login/', response.url)
@mock.patch('interventions.views.calendar.can_view_intervention_summary', return_value=False)
@mock.patch('interventions.views.calendar.can_view_intervention', return_value=False)
@mock.patch('interventions.views.calendar.get_object_or_404')
def test_permission_denied_returns_403(self, mock_get_obj, mock_can_view, mock_can_view_summary):
mock_itv = mock.MagicMock(id=123)
mock_get_obj.return_value = mock_itv
user = DummyUser(id=99)
request = self._create_request(user)
response = intervention_calendar_details_ajax(request, intervention_id=123)
self.assertEqual(response.status_code, 403)
@mock.patch('interventions.views.calendar.can_view_intervention_summary', return_value=False)
@mock.patch('interventions.views.calendar.can_view_intervention', return_value=True)
@mock.patch('interventions.views.calendar.InterventionNote.objects')
@mock.patch('interventions.views.calendar.get_object_or_404')
def test_authorized_user_receives_notes_and_documents(
self, mock_get_obj, mock_notes_qs, mock_can_view, mock_can_view_summary
):
mock_itv = mock.MagicMock(id=123, title="Intervention Réparation Éclairage")
mock_get_obj.return_value = mock_itv
now = timezone.now()
author = DummyUser(id=1, first_name="Jean", last_name="Dupont")
# Notes
note1 = DummyNote(
id=1,
note_type=InterventionNote.NoteType.EQUIPMENT,
type_display="Matériel",
badge_class="text-bg-warning text-dark",
icon_class="bi-tools",
content="Nacelle 15m requise pour intervention sur mât",
note_time=now,
note_author=author,
)
note2 = DummyNote(
id=2,
note_type=InterventionNote.NoteType.IMPORTANT_INFO,
type_display="Information importante",
badge_class="text-bg-danger text-white",
icon_class="bi-exclamation-triangle-fill",
content="Attention présence de câbles haute tension à proximité",
note_time=now,
note_author=author,
updated_at=now,
updated_by=author,
)
mock_filtered_notes = mock.MagicMock()
mock_filtered_notes.select_related.return_value = mock_filtered_notes
mock_filtered_notes.annotate.return_value = mock_filtered_notes
mock_filtered_notes.order_by.return_value = [note1, note2]
mock_notes_qs.filter.return_value = mock_filtered_notes
# Documents
doc_img = DummyDoc(
id=10,
filename="photo_degats.jpg",
thumbnail_path="thumbnails/photo_degats.jpg",
upload_date=now,
uploaded_by=author,
)
doc_pdf = DummyDoc(
id=11,
filename="rapport_securite.pdf",
thumbnail_path=None,
upload_date=now,
uploaded_by=author,
)
mock_docs_qs = mock.MagicMock()
mock_docs_qs.select_related.return_value = mock_docs_qs
mock_docs_qs.order_by.return_value = [doc_img, doc_pdf]
mock_itv.documents = mock_docs_qs
user = DummyUser(id=99)
request = self._create_request(user)
response = intervention_calendar_details_ajax(request, intervention_id=123)
self.assertEqual(response.status_code, 200)
data = json.loads(response.content.decode('utf-8'))
self.assertTrue(data['success'])
self.assertEqual(data['notes_count'], 2)
self.assertEqual(data['documents_count'], 2)
self.assertEqual(data['total_count'], 4)
# Content assertions
self.assertIn("Nacelle 15m requise", data['html'])
self.assertIn("Attention présence de câbles haute tension", data['html'])
self.assertIn("photo_degats.jpg", data['html'])
self.assertIn("rapport_securite.pdf", data['html'])
self.assertIn("Jean D.", data['html'])
# Document flags computed by view
self.assertTrue(doc_img.is_image)
self.assertFalse(doc_img.is_pdf)
self.assertEqual(doc_img.ext, '.jpg')
self.assertFalse(doc_pdf.is_image)
self.assertTrue(doc_pdf.is_pdf)
self.assertEqual(doc_pdf.ext, '.pdf')
@mock.patch('interventions.views.calendar.can_view_intervention_summary', return_value=False)
@mock.patch('interventions.views.calendar.can_view_intervention', return_value=True)
@mock.patch('interventions.views.calendar.InterventionNote.objects')
@mock.patch('interventions.views.calendar.get_object_or_404')
def test_empty_notes_and_documents(
self, mock_get_obj, mock_notes_qs, mock_can_view, mock_can_view_summary
):
mock_itv = mock.MagicMock(id=456, title="Intervention Sans Notes")
mock_get_obj.return_value = mock_itv
mock_filtered_notes = mock.MagicMock()
mock_filtered_notes.select_related.return_value = mock_filtered_notes
mock_filtered_notes.annotate.return_value = mock_filtered_notes
mock_filtered_notes.order_by.return_value = []
mock_notes_qs.filter.return_value = mock_filtered_notes
mock_docs_qs = mock.MagicMock()
mock_docs_qs.select_related.return_value = mock_docs_qs
mock_docs_qs.order_by.return_value = []
mock_itv.documents = mock_docs_qs
user = DummyUser(id=99)
request = self._create_request(user)
response = intervention_calendar_details_ajax(request, intervention_id=456)
self.assertEqual(response.status_code, 200)
data = json.loads(response.content.decode('utf-8'))
self.assertTrue(data['success'])
self.assertEqual(data['notes_count'], 0)
self.assertEqual(data['documents_count'], 0)
self.assertEqual(data['total_count'], 0)
self.assertIn("Aucune note ni document", data['html'])