ScoDoc/tests/api/test_api_assiduites.py

412 lines
12 KiB
Python

"""
Test de l'api Assiduité
Ecrit par HARTMANN Matthias
"""
from random import randint
from tests.api.setup_test_api import (
GET,
POST_JSON,
APIError,
api_headers,
api_admin_headers,
)
ETUDID = 1
FAUX = 42069
FORMSEMESTREID = 1
MODULE = 1
ASSIDUITES_FIELDS = {
"assiduite_id": int,
"etudid": int,
"code_nip": str,
"moduleimpl_id": int,
"date_debut": str,
"date_fin": str,
"etat": str,
"desc": str,
"entry_date": str,
"user_id": str,
"est_just": bool,
"external_data": dict,
}
CREATE_FIELD = {"assiduite_id": int}
BATCH_FIELD = {"errors": list, "success": list}
COUNT_FIELDS = {"compte": int, "journee": int, "demi": int, "heure": float}
TO_REMOVE = []
def check_fields(data: dict, fields: dict = None):
"""
Cette fonction permet de vérifier que le dictionnaire data
contient les bonnes clés et les bons types de valeurs.
Args:
data (dict): un dictionnaire (json de retour de l'api)
fields (dict, optional): Un dictionnaire représentant les clés et les types d'une réponse.
"""
if fields is None:
fields = ASSIDUITES_FIELDS
assert set(data.keys()) == set(fields.keys())
for key in data:
if key in ("moduleimpl_id", "desc", "user_id", "external_data"):
assert (
isinstance(data[key], fields[key]) or data[key] is None
), f"error [{key}:{type(data[key])}, {data[key]}, {fields[key]}]"
else:
assert isinstance(
data[key], fields[key]
), f"error [{key}:{type(data[key])}, {data[key]}, {fields[key]}]"
def check_failure_get(path: str, headers: dict, err: str = None):
"""
Cette fonction vérifiée que la requête GET renvoie bien un 404
Args:
path (str): la route de l'api
headers (dict): le token d'auth de l'api
err (str, optional): L'erreur qui est sensée être fournie par l'api.
Raises:
APIError: Une erreur car la requête a fonctionné (mauvais comportement)
"""
try:
GET(path=path, headers=headers)
# ^ Renvoi un 404
except APIError as api_err:
if err is not None:
assert api_err.payload["message"] == err
else:
raise APIError("Le GET n'aurait pas du fonctionner")
def check_failure_post(path: str, headers: dict, data: dict, err: str = None):
"""
Cette fonction vérifiée que la requête POST renvoie bien un 404
Args:
path (str): la route de l'api
headers (dict): le token d'auth
data (dict): un dictionnaire (json) à envoyer
err (str, optional): L'erreur qui est sensée être fournie par l'api.
Raises:
APIError: Une erreur car la requête a fonctionné (mauvais comportement)
"""
try:
data = POST_JSON(path=path, headers=headers, data=data)
# ^ Renvoi un 404
except APIError as api_err:
if err is not None:
assert api_err.payload["message"] == err
else:
raise APIError("Le GET n'aurait pas du fonctionner")
def create_data(etat: str, day: str, module: int = None, desc: str = None):
"""
Permet de créer un dictionnaire assiduité
Args:
etat (str): l'état de l'assiduité (PRESENT,ABSENT,RETARD)
day (str): Le jour de l'assiduité
module (int, optional): Le moduleimpl_id associé
desc (str, optional): Une description de l'assiduité (eg: motif retard )
Returns:
dict: la représentation d'une assiduité
"""
data = {
"date_debut": f"2022-01-{day}T08:00",
"date_fin": f"2022-01-{day}T10:00",
"etat": etat,
}
if module is not None:
data["moduleimpl_id"] = module
if desc is not None:
data["desc"] = desc
return data
def test_route_assiduite(api_headers):
"""test de la route /assiduite/<assiduite_id:int>"""
# Bon fonctionnement == id connu
data = GET(path="/assiduite/1", headers=api_headers)
check_fields(data)
# Mauvais Fonctionnement == id inconnu
check_failure_get(
f"/assiduite/{FAUX}",
api_headers,
)
def test_route_count_assiduites(api_headers):
"""test de la route /assiduites/<etudid:int>/count"""
# Bon fonctionnement
data = GET(path=f"/assiduites/{ETUDID}/count", headers=api_headers)
check_fields(data, COUNT_FIELDS)
metrics = {"heure", "compte"}
data = GET(
path=f"/assiduites/{ETUDID}/count/query?metric={','.join(metrics)}",
headers=api_headers,
)
assert set(data.keys()) == metrics
# Mauvais fonctionnement
check_failure_get(f"/assiduites/{FAUX}/count", api_headers)
def test_route_assiduites(api_headers):
"""test de la route /assiduites/<etudid:int>"""
# Bon fonctionnement
data = GET(path=f"/assiduites/{ETUDID}", headers=api_headers)
assert isinstance(data, list)
for ass in data:
check_fields(ass, ASSIDUITES_FIELDS)
data = GET(path=f"/assiduites/{ETUDID}/query?", headers=api_headers)
assert isinstance(data, list)
for ass in data:
check_fields(ass, ASSIDUITES_FIELDS)
# Mauvais fonctionnement
check_failure_get(f"/assiduites/{FAUX}", api_headers)
check_failure_get(f"/assiduites/{FAUX}/query?", api_headers)
def test_route_formsemestre_assiduites(api_headers):
"""test de la route /assiduites/formsemestre/<formsemestre_id:int>"""
# Bon fonctionnement
data = GET(path=f"/assiduites/formsemestre/{FORMSEMESTREID}", headers=api_headers)
assert isinstance(data, list)
for ass in data:
check_fields(ass, ASSIDUITES_FIELDS)
data = GET(
path=f"/assiduites/formsemestre/{FORMSEMESTREID}/query?", headers=api_headers
)
assert isinstance(data, list)
for ass in data:
check_fields(ass, ASSIDUITES_FIELDS)
# Mauvais fonctionnement
check_failure_get(
f"/assiduites/formsemestre/{FAUX}",
api_headers,
err="le paramètre 'formsemestre_id' n'existe pas",
)
check_failure_get(
f"/assiduites/formsemestre/{FAUX}/query?",
api_headers,
err="le paramètre 'formsemestre_id' n'existe pas",
)
def test_route_count_formsemestre_assiduites(api_headers):
"""test de la route /assiduites/formsemestre/<formsemestre_id:int>/count"""
# Bon fonctionnement
data = GET(
path=f"/assiduites/formsemestre/{FORMSEMESTREID}/count", headers=api_headers
)
check_fields(data, COUNT_FIELDS)
metrics = {"heure", "compte"}
data = GET(
path=f"/assiduites/formsemestre/{FORMSEMESTREID}/count/query?metric={','.join(metrics)}",
headers=api_headers,
)
assert set(data.keys()) == metrics
# Mauvais fonctionnement
check_failure_get(
f"/assiduites/formsemestre/{FAUX}/count",
api_headers,
err="le paramètre 'formsemestre_id' n'existe pas",
)
check_failure_get(
f"/assiduites/formsemestre/{FAUX}/count/query?",
api_headers,
err="le paramètre 'formsemestre_id' n'existe pas",
)
def test_route_create(api_admin_headers):
"""test de la route /assiduite/<etudid:int>/create"""
# -== Unique ==-
# Bon fonctionnement
data = create_data("present", "01")
res = POST_JSON(f"/assiduite/{ETUDID}/create", [data], api_admin_headers)
check_fields(res, BATCH_FIELD)
assert len(res["success"]) == 1
TO_REMOVE.append(res["success"][0]["message"]["assiduite_id"])
data = GET(
path=f'/assiduite/{res["success"][0]["message"]["assiduite_id"]}',
headers=api_admin_headers,
)
check_fields(data)
data2 = create_data("absent", "02", MODULE, "desc")
res = POST_JSON(f"/assiduite/{ETUDID}/create", [data2], api_admin_headers)
check_fields(res, BATCH_FIELD)
assert len(res["success"]) == 1
TO_REMOVE.append(res["success"][0]["message"]["assiduite_id"])
# Mauvais fonctionnement
check_failure_post(f"/assiduite/{FAUX}/create", api_admin_headers, [data])
res = POST_JSON(f"/assiduite/{ETUDID}/create", [data], api_admin_headers)
check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 1
assert (
res["errors"][0]["message"]
== "Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
)
res = POST_JSON(
f"/assiduite/{ETUDID}/create",
[create_data("absent", "03", FAUX)],
api_admin_headers,
)
check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 1
assert res["errors"][0]["message"] == "param 'moduleimpl_id': invalide"
# -== Multiple ==-
# Bon Fonctionnement
etats = ["present", "absent", "retard"]
data = [
create_data(etats[d % 3], 10 + d, MODULE if d % 2 else None)
for d in range(randint(3, 5))
]
res = POST_JSON(f"/assiduite/{ETUDID}/create", data, api_admin_headers)
check_fields(res, BATCH_FIELD)
for dat in res["success"]:
check_fields(dat["message"], CREATE_FIELD)
TO_REMOVE.append(dat["message"]["assiduite_id"])
# Mauvais Fonctionnement
data2 = [
create_data("present", "01"),
create_data("present", "25", FAUX),
create_data("blabla", 26),
create_data("absent", 32),
]
res = POST_JSON(f"/assiduite/{ETUDID}/create", data2, api_admin_headers)
check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 4
assert (
res["errors"][0]["message"]
== "Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
)
assert res["errors"][1]["message"] == "param 'moduleimpl_id': invalide"
assert res["errors"][2]["message"] == "param 'etat': invalide"
assert (
res["errors"][3]["message"]
== "param 'date_debut': format invalide, param 'date_fin': format invalide"
)
def test_route_edit(api_admin_headers):
"""test de la route /assiduite/<assiduite_id:int>/edit"""
# Bon fonctionnement
data = {"etat": "retard", "moduleimpl_id": MODULE}
res = POST_JSON(f"/assiduite/{TO_REMOVE[0]}/edit", data, api_admin_headers)
assert res == {"OK": True}
data["moduleimpl_id"] = None
res = POST_JSON(f"/assiduite/{TO_REMOVE[1]}/edit", data, api_admin_headers)
assert res == {"OK": True}
# Mauvais fonctionnement
check_failure_post(f"/assiduite/{FAUX}/edit", api_admin_headers, data)
data["etat"] = "blabla"
check_failure_post(
f"/assiduite/{TO_REMOVE[2]}/edit",
api_admin_headers,
data,
err="param 'etat': invalide",
)
def test_route_delete(api_admin_headers):
"""test de la route /assiduite/delete"""
# -== Unique ==-
# Bon fonctionnement
data = TO_REMOVE[0]
res = POST_JSON("/assiduite/delete", [data], api_admin_headers)
check_fields(res, BATCH_FIELD)
for dat in res["success"]:
assert dat["message"] == "OK"
# Mauvais fonctionnement
res = POST_JSON("/assiduite/delete", [data], api_admin_headers)
check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 1
# -== Multiple ==-
# Bon Fonctionnement
data = TO_REMOVE[1:]
res = POST_JSON("/assiduite/delete", data, api_admin_headers)
check_fields(res, BATCH_FIELD)
for dat in res["success"]:
assert dat["message"] == "OK"
# Mauvais Fonctionnement
data2 = [
FAUX,
FAUX + 1,
FAUX + 2,
]
res = POST_JSON("/assiduite/delete", data2, api_admin_headers)
check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 3
assert all(i["message"] == "Assiduite non existante" for i in res["errors"])