Un code-barre inconnu scanné propose désormais le même formulaire de création que /materiels au lieu d'un simple message d'erreur. La quantité peut être ajustée d'un delta choisi librement (pas figé à ±1) ou définie directement à une valeur absolue après un inventaire. La racine "/" sert directement la liste des matériels sans redirection. La page Matériels gagne un filtre par catégorie, un filtre stock bas, et un tri incluant un regroupement par catégorie.
114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
"""
|
|
Tests du filtre/tri de /materiels : recherche, filtre par catégorie (avec
|
|
ses sous-catégories), filtre stock bas, et tri (dont le regroupement par
|
|
catégorie), combinables entre eux.
|
|
"""
|
|
|
|
from sqlmodel import Session
|
|
|
|
from app.models import Categorie, Materiel
|
|
|
|
|
|
def _arborescence(session: Session) -> dict[str, Categorie]:
|
|
"""Ordinateurs > Portables, Réseau > Câbles — deux branches pour
|
|
tester le filtre par catégorie et le regroupement."""
|
|
ordinateurs = Categorie(nom="Ordinateurs")
|
|
session.add(ordinateurs)
|
|
session.commit()
|
|
session.refresh(ordinateurs)
|
|
portables = Categorie(nom="Portables", parent_id=ordinateurs.id)
|
|
session.add(portables)
|
|
session.commit()
|
|
session.refresh(portables)
|
|
|
|
reseau = Categorie(nom="Réseau")
|
|
session.add(reseau)
|
|
session.commit()
|
|
session.refresh(reseau)
|
|
cables = Categorie(nom="Câbles", parent_id=reseau.id)
|
|
session.add(cables)
|
|
session.commit()
|
|
session.refresh(cables)
|
|
|
|
return {"ordinateurs": ordinateurs, "portables": portables, "reseau": reseau, "cables": cables}
|
|
|
|
|
|
def _materiels_demo(session: Session, categories: dict[str, Categorie]) -> None:
|
|
session.add_all(
|
|
[
|
|
Materiel(
|
|
nom="PC Dell XPS 13",
|
|
categorie_id=categories["portables"].id,
|
|
quantite=2,
|
|
seuil_alerte=5,
|
|
),
|
|
Materiel(
|
|
nom="PC Lenovo T14",
|
|
categorie_id=categories["portables"].id,
|
|
quantite=8,
|
|
seuil_alerte=3,
|
|
),
|
|
Materiel(
|
|
nom="Câble RJ45 2m",
|
|
categorie_id=categories["cables"].id,
|
|
quantite=40,
|
|
seuil_alerte=10,
|
|
),
|
|
]
|
|
)
|
|
session.commit()
|
|
|
|
|
|
def test_filtre_par_categorie_inclut_les_sous_categories(client, session):
|
|
categories = _arborescence(session)
|
|
_materiels_demo(session, categories)
|
|
|
|
reponse = client.get("/materiels", params={"categorie_id": categories["ordinateurs"].id})
|
|
|
|
assert "PC Dell XPS 13" in reponse.text
|
|
assert "PC Lenovo T14" in reponse.text
|
|
assert "Câble RJ45 2m" not in reponse.text
|
|
|
|
|
|
def test_filtre_stock_bas(client, session):
|
|
categories = _arborescence(session)
|
|
_materiels_demo(session, categories)
|
|
|
|
reponse = client.get("/materiels", params={"stock_bas": "1"})
|
|
|
|
assert "PC Dell XPS 13" in reponse.text # 2 < seuil 5
|
|
assert "PC Lenovo T14" not in reponse.text # 8 >= seuil 3
|
|
assert "Câble RJ45 2m" not in reponse.text # 40 >= seuil 10
|
|
|
|
|
|
def test_tri_par_quantite_decroissant(client, session):
|
|
categories = _arborescence(session)
|
|
_materiels_demo(session, categories)
|
|
|
|
reponse = client.get("/materiels", params={"tri": "quantite_desc"})
|
|
|
|
position_cable = reponse.text.index("Câble RJ45 2m")
|
|
position_lenovo = reponse.text.index("PC Lenovo T14")
|
|
position_dell = reponse.text.index("PC Dell XPS 13")
|
|
assert position_cable < position_lenovo < position_dell
|
|
|
|
|
|
def test_tri_categorie_regroupe_les_materiels(client, session):
|
|
categories = _arborescence(session)
|
|
_materiels_demo(session, categories)
|
|
|
|
reponse = client.get("/materiels", params={"tri": "categorie"})
|
|
|
|
assert "groupe-categorie-entete" in reponse.text
|
|
assert "Ordinateurs / Portables" in reponse.text
|
|
assert "Réseau / Câbles" in reponse.text
|
|
|
|
|
|
def test_recherche_et_filtre_categorie_combines(client, session):
|
|
categories = _arborescence(session)
|
|
_materiels_demo(session, categories)
|
|
|
|
reponse = client.get("/materiels", params={"q": "PC", "categorie_id": categories["reseau"].id})
|
|
|
|
assert "Aucun matériel ne correspond" in reponse.text
|