loko/streetup/assets/tests_inspections_views.py

226 lines
9.8 KiB
Python

from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from assets.models.parking import ParkingSpot
from assets.models.inspection import AssetInspection, ParkingSpotInspection
from interventions.models import Intervention
User = get_user_model()
class InspectionViewsTestCase(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username='test_inspector',
password='password123',
first_name='Jean',
last_name='Dupont'
)
from common.models import UserConfig
UserConfig.objects.get_or_create(user=self.user)
self.client = Client()
self.client.login(username='test_inspector', password='password123')
self.spot = ParkingSpot.objects.create(
code='PK-001',
name_fr='Emplacement Vélo Test',
spot_type='bicycle',
standard_stand_count=5
)
self.spot_ct = ContentType.objects.get_for_model(ParkingSpot)
def test_inspections_list_view(self):
insp = AssetInspection.objects.create(
asset_content_type=self.spot_ct,
asset_object_id=self.spot.id,
inspector=self.user,
result_status='compliant',
nature='visual'
)
response = self.client.get(reverse('assets:inspections_list'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'PK-001')
self.assertContains(response, 'Mes inspections')
def test_quick_inspection_map_view(self):
response = self.client.get(reverse('assets:quick_inspection_map'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Inspection Rapide')
def test_quick_inspection_map_mobile_view(self):
response = self.client.get(reverse('mobile:quick_inspection_map_mobile'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Inspection Rapide')
def test_create_inspection_api_compliant(self):
response = self.client.post(reverse('assets:create_inspection_api'), {
'content_type_id': self.spot_ct.id,
'object_id': self.spot.id,
'result_status': 'compliant',
'nature': 'visual',
'inspector_role': 'observer',
'notes': 'Tout est parfait',
})
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data['success'])
self.spot.refresh_from_db()
self.assertEqual(self.spot.inspection_status, 'compliant')
self.assertTrue(self.spot.is_compliant)
def test_create_inspection_api_damaged_creates_intervention(self):
response = self.client.post(reverse('assets:create_inspection_api'), {
'content_type_id': self.spot_ct.id,
'object_id': self.spot.id,
'result_status': 'damaged',
'nature': 'visual',
'notes': 'Arceau tordu',
'create_intervention': 'true',
})
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data['success'])
self.assertIsNotNone(data['created_intervention_code'])
self.spot.refresh_from_db()
self.assertEqual(self.spot.inspection_status, 'damaged')
self.assertFalse(self.spot.is_compliant)
interv = Intervention.objects.filter(code=data['created_intervention_code']).first()
self.assertIsNotNone(interv)
self.assertEqual(interv.status, 'in_preparation')
def test_quick_inspection_map_permissions_can_inspect(self):
from common.models import UserConfig, UserThematics, Thematic
t_parking = Thematic.objects.get(code='parking')
t_other, _ = Thematic.objects.get_or_create(code='publiclighting', defaults={'name_fr': 'Éclairage public'})
user_config, _ = UserConfig.objects.get_or_create(user=self.user)
UserThematics.objects.create(user_config=user_config, thematic=t_parking, can_inspect=True)
UserThematics.objects.create(user_config=user_config, thematic=t_other, can_inspect=False)
response = self.client.get(reverse('assets:quick_inspection_map'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'parking')
self.assertNotContains(response, 'publiclighting')
def test_no_inspectable_thematic_hides_button_and_returns_403(self):
from common.models import UserConfig, UserThematics, Thematic
t_parking = Thematic.objects.get(code='parking')
user_config, _ = UserConfig.objects.get_or_create(user=self.user)
UserThematics.objects.create(user_config=user_config, thematic=t_parking, can_inspect=False)
# 1. Page liste des inspections -> Bouton 'Nouvelle inspection' masqué
resp_list = self.client.get(reverse('assets:inspections_list'))
self.assertEqual(resp_list.status_code, 200)
self.assertNotContains(resp_list, reverse('assets:quick_inspection_map'))
# 2. Tentative d'accès direct à quick_inspection_map -> HTTP 403 Forbidden
resp_map = self.client.get(reverse('assets:quick_inspection_map'))
self.assertEqual(resp_map.status_code, 403)
def test_create_inspection_api_with_photo(self):
from django.core.files.uploadedfile import SimpleUploadedFile
test_photo = SimpleUploadedFile("test_inspection.jpg", b"fake_image_bytes", content_type="image/jpeg")
response = self.client.post(reverse('assets:create_inspection_api'), {
'content_type_id': self.spot_ct.id,
'object_id': self.spot.id,
'result_status': 'compliant',
'nature': 'visual',
'notes': 'Inspection avec photo',
'photos': [test_photo],
})
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data['success'])
inspection = AssetInspection.objects.get(id=data['inspection_id'])
self.assertEqual(inspection.documents.count(), 1)
doc = inspection.documents.first()
self.assertTrue(doc.is_image)
self.assertTrue(doc.filename.startswith('test_inspection'))
def test_inspections_geojson_view(self):
from django.contrib.gis.geos import Polygon
self.spot.geom = Polygon(((4.35, 50.85), (4.36, 50.85), (4.36, 50.86), (4.35, 50.86), (4.35, 50.85)), srid=4326)
self.spot.save()
insp = AssetInspection.objects.create(
asset_content_type=self.spot_ct,
asset_object_id=self.spot.id,
inspector=self.user,
result_status='compliant',
nature='visual'
)
response = self.client.post(
reverse('assets:inspections_geojson'),
data={'thematic': 'parking', 'period': '3m'},
content_type='application/json'
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertEqual(data['type'], 'FeatureCollection')
self.assertEqual(data['features'][0]['properties']['inspections'][0]['id'], insp.id)
self.assertEqual(data['features'][0]['properties']['inspections_count'], 1)
def test_inspections_list_search_by_asset_code(self):
self.spot.code = "SPOT-TEST-SEARCH-99"
self.spot.save()
insp = AssetInspection.objects.create(
asset_content_type=self.spot_ct,
asset_object_id=self.spot.id,
inspector=self.user,
result_status='compliant',
nature='visual'
)
response = self.client.get(reverse('assets:inspections_list') + '?tab=all&q=SEARCH-99')
self.assertEqual(response.status_code, 200)
self.assertIn(insp, response.context['inspections'])
def test_inspections_list_filter_thematics_uses_can_view_assets(self):
from common.models import UserConfig, UserThematics, Thematic
t_parking = Thematic.objects.get(code='parking')
t_lighting, _ = Thematic.objects.get_or_create(code='publiclighting', defaults={'name_fr': 'Éclairage public'})
user_config, _ = UserConfig.objects.get_or_create(user=self.user)
# L'utilisateur a les droits de voir les assets parking mais pas d'inspecter, et pas de voir l'éclairage public
UserThematics.objects.create(user_config=user_config, thematic=t_parking, can_view_assets=True, can_inspect=False)
UserThematics.objects.create(user_config=user_config, thematic=t_lighting, can_view_assets=False, can_inspect=False)
resp = self.client.get(reverse('assets:inspections_list'))
self.assertEqual(resp.status_code, 200)
self.assertIn(t_parking, resp.context['thematics'])
self.assertNotIn(t_lighting, resp.context['thematics'])
self.assertFalse(resp.context['can_inspect'])
def test_user_without_config_returns_none(self):
from assets.views.inspections import get_user_viewable_thematics, get_user_inspectable_thematics
user_no_config = User.objects.create_user(username='no_config_user', password='pwd')
self.assertIsNone(get_user_viewable_thematics(user_no_config))
self.assertIsNone(get_user_inspectable_thematics(user_no_config))
def test_asset_inspections_templatetag(self):
from assets.templatetags.asset_tags import asset_inspections
from assets.models import AssetInspection
insp = AssetInspection.objects.create(
asset=self.spot,
inspector=self.user,
result_status='compliant',
nature='visual'
)
dummy_context = {'request': self.client.get('/').wsgi_request}
data = asset_inspections(dummy_context, self.spot)
self.assertEqual(data['total_count'], 1)
self.assertIn(insp, data['inspections'])
self.assertEqual(data['asset_pk'], self.spot.pk)