Skip to content

Commit

Permalink
Trier les fiches de détection par numéro séquentiel et non par ID
Browse files Browse the repository at this point in the history
- Sélectionner la première fiche de détection par numéro et non par ID dans la vue détail événement
-  MAJ des tests avec factories
  * Remplacement de baker par des factories dans quelques tests
  * Ajout d'une méthode create_miniaml pour créer une factory Lieu ou Prelevement avec uniquement les champs obligatoires
  * Ajout de la factory PosistionChaineDistribution
  • Loading branch information
alanzirek committed Feb 28, 2025
1 parent 1fc082f commit 6112a8a
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 33 deletions.
45 changes: 45 additions & 0 deletions sv/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SITES_INSPECTION,
DEPARTEMENTS,
REGIONS,
POSITION_CHAINE_DISTRIBUTION,
)
from .models import (
Prelevement,
Expand All @@ -36,6 +37,7 @@
Contexte,
SiteInspection,
Region,
PositionChaineDistribution,
)

fake = Faker()
Expand Down Expand Up @@ -187,6 +189,26 @@ def build_with_some_related_objects_saved(cls, *args, **kwargs):
espece = EspeceEchantillonFactory()
return cls.build(matrice_prelevee=matrice_prelevee, espece_echantillon=espece, *args, **kwargs)

@classmethod
def create_minimal(cls, **kwargs):
return cls.create(
numero_echantillon="",
date_prelevement=None,
matrice_prelevee=None,
espece_echantillon=None,
laboratoire=None,
numero_rapport_inspection="",
**kwargs,
)


class PositionChaineDistributionFactory(DjangoModelFactory):
class Meta:
model = PositionChaineDistribution
django_get_or_create = ("libelle",)

libelle = factory.lazy_attribute(lambda _: random.choice(POSITION_CHAINE_DISTRIBUTION))


class LieuFactory(DjangoModelFactory):
class Meta:
Expand All @@ -210,6 +232,29 @@ class Meta:
siret_etablissement = factory.Faker("numerify", text="##############")
code_inupp_etablissement = factory.Faker("numerify", text="#######")
site_inspection = factory.SubFactory("sv.factories.SiteInspectionFactory")
position_chaine_distribution_etablissement = factory.SubFactory("sv.factories.PositionChaineDistributionFactory")

@classmethod
def create_minimal(cls, **kwargs):
return cls.create(
wgs84_longitude=None,
wgs84_latitude=None,
adresse_lieu_dit="",
commune="",
code_insee="",
departement=None,
is_etablissement=False,
nom_etablissement="",
activite_etablissement="",
pays_etablissement="",
raison_sociale_etablissement="",
adresse_etablissement="",
siret_etablissement="",
code_inupp_etablissement="",
site_inspection=None,
position_chaine_distribution_etablissement=None,
**kwargs,
)


class FicheDetectionFactory(DjangoModelFactory):
Expand Down
30 changes: 30 additions & 0 deletions sv/tests/test_evenement_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,33 @@ def test_show_details_synthese_switch(live_server, page: Page, etat: Etat):
page.goto(f"{live_server.url}{evenement.get_absolute_url()}")
expect(page.get_by_text("Détail")).to_be_visible()
expect(page.get_by_text("Synthèse")).to_be_visible()


def test_first_detection_by_number_is_selected_by_default(live_server, page: Page):
"""Test que la première fiche de détection (par numéro et non par id) est sélectionnée par défaut."""
evenement = EvenementFactory()

FicheDetectionFactory(evenement=evenement, numero_detection=f"{evenement.numero}.3")
FicheDetectionFactory(evenement=evenement, numero_detection=f"{evenement.numero}.2")
detection_3 = FicheDetectionFactory(evenement=evenement, numero_detection=f"{evenement.numero}.1")

page.goto(f"{live_server.url}{evenement.get_absolute_url()}")

expect(page.get_by_role("tab", name=detection_3.numero_detection)).to_have_class(
re.compile(r"(^|\s)selected($|\s)")
)


def test_detections_are_order_by_detection_number_not_by_id(live_server, page: Page):
"""Test que les fiches détections sont triées par numéro et non par id."""
evenement = EvenementFactory()
detection_10 = FicheDetectionFactory(evenement=evenement, numero_detection=f"{evenement.numero}.10")
detection_3 = FicheDetectionFactory(evenement=evenement, numero_detection=f"{evenement.numero}.3")
detection_2 = FicheDetectionFactory(evenement=evenement, numero_detection=f"{evenement.numero}.2")
detection_1 = FicheDetectionFactory(evenement=evenement, numero_detection=f"{evenement.numero}.1")

page.goto(f"{live_server.url}{evenement.get_absolute_url()}")

expect(page.locator("#tabpanel-detection-panel ul > li")).to_contain_text(
[detection_1.numero, detection_2.numero, detection_3.numero, detection_10.numero]
)
2 changes: 1 addition & 1 deletion sv/tests/test_evenement_performance_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def test_evenement_performances_with_prelevement(client, django_assert_num_queri

PrelevementFactory.create_batch(3, lieu__fiche_detection=fiche_detection)

with django_assert_num_queries(BASE_NUM_QUERIES + 12):
with django_assert_num_queries(BASE_NUM_QUERIES + 13):
client.get(evenement.get_absolute_url())


Expand Down
42 changes: 14 additions & 28 deletions sv/tests/test_fichedetection_detail.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
from model_bakery import baker
from playwright.sync_api import expect

from sv.factories import LieuFactory, EvenementFactory, FicheDetectionFactory, PrelevementFactory
from sv.models import Lieu, Prelevement
from sv.models import Prelevement


def test_lieu_details(live_server, page, fiche_detection):
def test_lieu_details(live_server, page):
"Test que les détails d'un lieu s'affichent correctement dans la modale"
lieu = baker.make(Lieu, fiche_detection=fiche_detection, _fill_optional=True, is_etablissement=True)
evenement = fiche_detection.evenement
evenement.createur = fiche_detection.createur
evenement.save()
page.goto(f"{live_server.url}{fiche_detection.get_absolute_url()}")
lieu = LieuFactory(is_etablissement=True)
page.goto(f"{live_server.url}{lieu.fiche_detection.get_absolute_url()}")
page.get_by_role("button", name=f"Consulter le détail du lieu {lieu.nom}").click()
expect(page.get_by_role("heading", name=lieu.nom)).to_be_visible()
expect(page.locator(f"#fr-modal-lieu-{lieu.pk}").get_by_text("Adresse ou lieu-dit")).to_be_visible()
Expand Down Expand Up @@ -48,14 +44,10 @@ def test_lieu_details(live_server, page, fiche_detection):
)


def test_lieu_details_second_lieu(live_server, page, fiche_detection):
def test_lieu_details_second_lieu(live_server, page):
"Test que si je clique sur le bouton 'Consulter le détail du lieu' d'un deuxième lieu, les détails de ce lieu s'affichent correctement dans la modale"
baker.make(Lieu, fiche_detection=fiche_detection, _fill_optional=True)
evenement = fiche_detection.evenement
evenement.createur = fiche_detection.createur
evenement.save()
lieu2 = baker.make(Lieu, fiche_detection=fiche_detection, _fill_optional=True)
page.goto(f"{live_server.url}{fiche_detection.get_absolute_url()}")
_, lieu2 = LieuFactory.create_batch(2)
page.goto(f"{live_server.url}{lieu2.fiche_detection.get_absolute_url()}")
page.get_by_role("button", name=f"Consulter le détail du lieu {lieu2.nom}").click()
expect(page.get_by_role("heading", name=lieu2.nom)).to_be_visible()
expect(page.get_by_test_id(f"lieu-{lieu2.pk}-adresse")).to_contain_text(lieu2.adresse_lieu_dit)
Expand Down Expand Up @@ -93,13 +85,10 @@ def test_lieu_details_of_second_detection_when_first_detection_has_lieu(live_ser
expect(page.locator(".fr-modal--opened")).to_contain_text(str(lieu.wgs84_longitude).replace(".", ","))


def test_lieu_details_with_no_data(live_server, page, fiche_detection):
def test_lieu_details_with_no_data(live_server, page):
"Test que les détails d'un lieu s'affichent correctement dans la modale lorsqu'il n'y a pas de données (sauf pour les champs obligatoires)"
lieu = baker.make(Lieu, fiche_detection=fiche_detection)
evenement = fiche_detection.evenement
evenement.createur = fiche_detection.createur
evenement.save()
page.goto(f"{live_server.url}{fiche_detection.get_absolute_url()}")
lieu = LieuFactory.create_minimal()
page.goto(f"{live_server.url}{lieu.fiche_detection.get_absolute_url()}")
page.get_by_role("button", name=f"Consulter le détail du lieu {lieu.nom}").click()
expect(page.get_by_test_id(f"lieu-{lieu.pk}-adresse")).to_contain_text("nc.")
expect(page.get_by_test_id(f"lieu-{lieu.pk}-commune")).to_contain_text(lieu.commune)
Expand All @@ -121,14 +110,11 @@ def test_prelevement_card(live_server, page):
expect(page.locator(".prelevement").get_by_text("DÉTECTÉ")).to_be_visible()


def test_prelevement_non_officiel_details_with_no_data(live_server, page, fiche_detection):
def test_prelevement_non_officiel_details_with_no_data(live_server, page):
"Test que les détails d'un prélèvement non officiel s'affichent correctement dans la modale lorsqu'il n'y a pas de données (sauf pour les champs obligatoires)"
lieu = baker.make(Lieu, fiche_detection=fiche_detection)
evenement = fiche_detection.evenement
evenement.createur = fiche_detection.createur
evenement.save()
prelevement = baker.make(Prelevement, lieu=lieu)
page.goto(f"{live_server.url}{fiche_detection.get_absolute_url()}")
prelevement = PrelevementFactory.create_minimal(is_officiel=False)

page.goto(f"{live_server.url}{prelevement.lieu.fiche_detection.get_absolute_url()}")
page.get_by_role("button", name=f"Consulter le détail du prélèvement {prelevement.numero_echantillon}").click()
expect(page.get_by_test_id(f"prelevement-{prelevement.pk}-is-officiel")).to_contain_text(
"oui" if prelevement.is_officiel else "non"
Expand Down
12 changes: 8 additions & 4 deletions sv/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import PermissionDenied, ValidationError
from django.db import transaction
from django.db.models import Prefetch, Min
from django.db.models import Prefetch
from django.http import HttpResponseBadRequest, HttpResponseRedirect, HttpResponse, Http404
from django.shortcuts import redirect
from django.urls import reverse
Expand Down Expand Up @@ -111,10 +111,14 @@ class EvenementDetailView(
def get_queryset(self):
return (
Evenement.objects.all()
.annotate(first_detection_id=Min("detections__id"))
.select_related("createur", "organisme_nuisible", "statut_reglementaire")
.prefetch_related(
"detections",
Prefetch(
"detections",
queryset=FicheDetection.objects.all()
.with_numero_detection_only()
.order_by("numero_detection_only"),
),
"detections__createur",
Prefetch(
"detections__lieux__prelevements",
Expand Down Expand Up @@ -179,7 +183,7 @@ def get_context_data(self, **kwargs):
context["active_detection"] = (
int(self.request.GET.get("detection"))
if self.request.GET.get("detection")
else self.object.first_detection_id # first_detection_id sera None s'il n'y a pas de détection
else getattr(self.object.detections.first(), "id", None)
)
context["max_upload_size_mb"] = MAX_UPLOAD_SIZE_MEGABYTES
return context
Expand Down

0 comments on commit 6112a8a

Please sign in to comment.