loko/loko/assets/tests_parking_inspections.py

203 lines
8.7 KiB
Python

from django.test import TestCase, Client
from django.contrib.auth.models import User
from django.contrib.gis.geos import Polygon, MultiPolygon
from django.urls import reverse
from django.utils import timezone
from assets.models import ParkingLocation, ParkingSpot, AssetInspection, ParkingSpotInspection
from common.models import Thematic, UserConfig, UserThematics
class ParkingSpotAndInspectionTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username="inspector_user", password="password123")
self.client = Client()
# Create thematic and user thematic permissions
self.thematic, _ = Thematic.objects.get_or_create(
code="parking",
defaults={
"name_fr": "Stationnement & Mobilité",
"name_nl": "Parkeren & Mobiliteit"
}
)
self.user_config = UserConfig.objects.create(user=self.user)
UserThematics.objects.create(
user_config=self.user_config,
thematic=self.thematic,
can_view_assets=True
)
self.client.force_login(self.user)
poly = Polygon(((648000, 670000), (648010, 670000), (648010, 670010), (648000, 670010), (648000, 670000)), srid=3812)
multi_poly = MultiPolygon(poly, srid=3812)
self.parking_loc = ParkingLocation.objects.create(
code="PARK-LOC-01",
name_fr="Zone vélo Grand Place",
geom=multi_poly
)
self.spot = ParkingSpot.objects.create(
code="SPOT-VELO-01",
name_fr="Stationnement vélo Grand Place",
location=self.parking_loc,
spot_type="bicycle",
standard_stand_count=3,
cargo_stand_count=2,
stand_type="mixed",
has_scooter_drop_zone=True,
geom=poly
)
def test_parking_spot_creation_and_stand_counts(self):
self.assertEqual(self.spot.standard_stand_count, 3)
self.assertEqual(self.spot.cargo_stand_count, 2)
self.assertEqual(self.spot.drop_off_stand_count, 0)
self.assertEqual(self.spot.total_stand_count, 5)
self.assertTrue(self.spot.has_scooter_drop_zone)
self.assertTrue(self.spot.is_compliant)
self.assertEqual(self.spot.inspection_status, "unknown")
self.assertIsNotNone(self.spot.geojson)
def test_parking_spot_inspection_default_does_not_update_counts(self):
# Par défaut, apply_physical_counts_to_asset est False
inspection = ParkingSpotInspection.objects.create(
asset=self.spot,
inspector=self.user,
inspection_date=timezone.now(),
result_status="updated",
verified_standard_stand_count=4,
verified_cargo_stand_count=3,
verified_has_scooter_drop_zone=True,
verified_marking_quality="good",
apply_changes_to_asset=True,
apply_physical_counts_to_asset=False,
notes="Arceaux constatés"
)
self.spot.refresh_from_db()
self.assertEqual(self.spot.standard_stand_count, 3) # Non modifié
self.assertEqual(self.spot.cargo_stand_count, 2) # Non modifié
self.assertEqual(self.spot.validation_status, "validated") # Statut génerique mis à jour
self.assertEqual(self.spot.inspection_status, "updated")
def test_parking_spot_inspection_with_counts_opt_in_updates_asset(self):
inspection = ParkingSpotInspection.objects.create(
asset=self.spot,
inspector=self.user,
inspection_date=timezone.now(),
result_status="updated",
verified_standard_stand_count=4,
verified_cargo_stand_count=3,
verified_drop_off_stand_count=5,
verified_has_scooter_drop_zone=True,
verified_marking_quality="good",
apply_changes_to_asset=True,
apply_physical_counts_to_asset=True,
notes="Ajout récent de 1 arceau classique et 1 arceau cargo"
)
self.spot.refresh_from_db()
self.assertEqual(self.spot.standard_stand_count, 4) # Modifié avec l'opt-in
self.assertEqual(self.spot.cargo_stand_count, 3) # Modifié avec l'opt-in
self.assertEqual(self.spot.drop_off_stand_count, 5) # Modifié avec l'opt-in
self.assertEqual(self.spot.total_stand_count, 12)
self.assertEqual(self.spot.validation_status, "validated")
self.assertEqual(self.spot.inspection_status, "updated")
self.assertIsNotNone(self.spot.last_inspection_date)
self.assertTrue(self.spot.is_compliant)
def test_generic_asset_inspection_non_compliance(self):
inspection = AssetInspection.objects.create(
asset=self.spot,
inspector=self.user,
inspection_date=timezone.now(),
result_status="non_compliant",
notes="Arceau cargo tordu suite à un choc de livraison",
apply_changes_to_asset=True
)
self.spot.refresh_from_db()
self.assertFalse(self.spot.is_compliant)
self.assertEqual(self.spot.inspection_status, "non_compliant")
self.assertEqual(self.spot.non_compliance_reason, "Arceau cargo tordu suite à un choc de livraison")
def test_parking_assets_geojson_view(self):
url = reverse('assets:parking_assets_geojson')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertEqual(data.get("type"), "FeatureCollection")
features = data.get("features", [])
self.assertEqual(len(features), 1)
feat = features[0]
self.assertEqual(feat["properties"]["code"], "SPOT-VELO-01")
self.assertEqual(feat["properties"]["standard_stand_count"], 3)
self.assertEqual(feat["properties"]["cargo_stand_count"], 2)
self.assertEqual(feat["properties"]["drop_off_stand_count"], 0)
self.assertEqual(feat["properties"]["total_stand_count"], 5)
self.assertTrue(feat["properties"]["has_scooter_drop_zone"])
def test_parking_assets_autocomplete_view(self):
url = reverse('assets:parking_autocomplete_assets')
response = self.client.get(url, {'q': 'Grand Place'})
self.assertEqual(response.status_code, 200)
data = response.json()
results = data.get("results", [])
self.assertEqual(len(results), 1)
self.assertEqual(results[0]["code"], "SPOT-VELO-01")
def test_parking_thematic_config(self):
from assets.views.core import build_thematic_config
config = build_thematic_config([self.thematic])
self.assertIn("parking", config)
self.assertEqual(config["parking"]["assets_geojson_url"], reverse("assets:parking_assets_geojson"))
self.assertEqual(config["parking"]["locations_geojson_url"], reverse("assets:parking_locations_geojson"))
def test_inspection_modal_title_and_thumbnails(self):
from django.contrib.contenttypes.models import ContentType
from django.core.files.uploadedfile import SimpleUploadedFile
from inspections.models import InspectionDocument
from django.utils.translation import activate
self.user_config.is_intern = True
self.user_config.save()
activate('fr')
# Create an inspection on this parking spot
inspection = ParkingSpotInspection.objects.create(
asset=self.spot,
inspector=self.user,
inspection_date=timezone.now(),
result_status="compliant",
verified_standard_stand_count=3,
notes="Inspection vélo conforme"
)
photo = SimpleUploadedFile("arceau_velo.jpg", b"\xff\xd8\xff\xe0testimage", content_type="image/jpeg")
doc_img = InspectionDocument.objects.create(inspection=inspection, file=photo)
url = reverse('assets:parking_assets_detail', kwargs={'asset_model': 'parkingspot', 'asset_id': self.spot.id})
# Test in French
self.client.cookies['django_language'] = 'fr'
response_fr = self.client.get(url)
self.assertEqual(response_fr.status_code, 200)
content_fr = response_fr.content.decode('utf-8')
self.assertIn("Détail de l'inspection", content_fr)
self.assertNotIn("Détail de \\", content_fr)
# Test in English
self.client.cookies['django_language'] = 'en'
response_en = self.client.get(url)
self.assertEqual(response_en.status_code, 200)
content_en = response_en.content.decode('utf-8')
self.assertIn("Inspection detail", content_en)
# Check thumbnail rendering
self.assertIn('data-src="', content_fr)
self.assertIn(doc_img.filename, content_fr)
self.assertIn('show.bs.modal', content_fr)