merge master

This commit is contained in:
leonard_montalbano 2022-05-06 12:14:56 +02:00
commit c0c4fd8a39
23 changed files with 654 additions and 490 deletions

View File

@ -123,39 +123,40 @@ def absences_just(etudid: int = None, nip: int = None, ine: int = None):
return jsonify(abs_just)
@bp.route(
"/absences/abs_group_etat/<int:group_id>",
methods=["GET"],
)
@bp.route(
"/absences/abs_group_etat/group_id/<int:group_id>/date_debut/<string:date_debut>/date_fin/<string:date_fin>",
methods=["GET"],
)
@token_auth.login_required
@token_permission_required(Permission.APIView)
def abs_groupe_etat( # XXX A REVOIR XXX
group_id: int, date_debut, date_fin, with_boursier=True, format="html"
):
"""
Liste des absences d'un ou plusieurs groupes entre deux dates
"""
return error_response(501, message="Not implemented")
# XXX TODO INACHEVEE
# @bp.route(
# "/absences/abs_group_etat/<int:group_id>",
# methods=["GET"],
# )
# @bp.route(
# "/absences/abs_group_etat/group_id/<int:group_id>/date_debut/<string:date_debut>/date_fin/<string:date_fin>",
# methods=["GET"],
# )
# @token_auth.login_required
# @token_permission_required(Permission.APIView)
# def abs_groupe_etat( # XXX A REVOIR XXX
# group_id: int, date_debut, date_fin, with_boursier=True, format="html"
# ):
# """
# Liste des absences d'un ou plusieurs groupes entre deux dates
# """
# return error_response(501, message="Not implemented")
# Fonction utilisée : app.scodoc.sco_groups.get_group_members() et app.scodoc.sco_abs.list_abs_date()
# # Fonction utilisée : app.scodoc.sco_groups.get_group_members() et app.scodoc.sco_abs.list_abs_date()
try:
# Utilisation de la fonction get_group_members
members = get_group_members(group_id)
except ValueError:
return error_response(
409, message="La requête ne peut être traitée en létat actuel"
)
# try:
# # Utilisation de la fonction get_group_members
# members = get_group_members(group_id)
# except ValueError:
# return error_response(
# 409, message="La requête ne peut être traitée en létat actuel"
# )
data = []
# Filtre entre les deux dates renseignées
for member in members:
abs = sco_abs.list_abs_date(member.id, date_debut, date_fin)
data.append(abs)
# data = []
# # Filtre entre les deux dates renseignées
# for member in members:
# abs = sco_abs.list_abs_date(member.id, date_debut, date_fin)
# data.append(abs)
# return jsonify(data) # XXX TODO faire en sorte de pouvoir renvoyer sa (ex to_dict() dans absences)
return error_response(501, message="Not implemented")
# # return jsonify(data) # XXX TODO faire en sorte de pouvoir renvoyer sa (ex to_dict() dans absences)
# return error_response(501, message="Not implemented")

View File

@ -441,14 +441,14 @@ def etudiant_bulletin_semestre(
@bp.route(
"/etudiant/etudid/<int:etudid>/semestre/<int:formsemestre_id>/groups",
"/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/groups",
methods=["GET"],
)
@bp.route(
"/etudiant/nip/<int:nip>/semestre/<int:formsemestre_id>/groups", methods=["GET"]
"/etudiant/nip/<int:nip>/formsemestre/<int:formsemestre_id>/groups", methods=["GET"]
)
@bp.route(
"/etudiant/ine/<int:ine>/semestre/<int:formsemestre_id>/groups", methods=["GET"]
"/etudiant/ine/<int:ine>/formsemestre/<int:formsemestre_id>/groups", methods=["GET"]
)
@token_auth.login_required
@token_permission_required(Permission.APIView)
@ -456,7 +456,7 @@ def etudiant_groups(
formsemestre_id: int, etudid: int = None, nip: int = None, ine: int = None
):
"""
Retourne la liste des groupes auxquels appartient l'étudiant dans le semestre indiqué
Retourne la liste des groupes auxquels appartient l'étudiant dans le formsemestre indiqué
formsemestre_id : l'id d'un formsemestre
etudid : l'etudid d'un étudiant

View File

@ -54,7 +54,7 @@ def evaluations(moduleimpl_id: int):
return jsonify(data)
@bp.route("/evaluations/eval_notes/<int:evaluation_id>", methods=["GET"])
@bp.route("/evaluation/eval_notes/<int:evaluation_id>", methods=["GET"])
@token_auth.login_required
@token_permission_required(Permission.APIView)
def evaluation_notes(evaluation_id: int):

View File

@ -228,7 +228,7 @@ def invalidate_formsemestre( # was inval_cache(formsemestre_id=None, pdfonly=Fa
if getattr(g, "defer_cache_invalidation", False):
g.sem_to_invalidate.add(formsemestre_id)
return
log("inval_cache, formsemestre_id={formsemestre_id} pdfonly={pdfonly}")
log(f"inval_cache, formsemestre_id={formsemestre_id} pdfonly={pdfonly}")
if formsemestre_id is None:
# clear all caches
log("----- invalidate_formsemestre: clearing all caches -----")
@ -272,7 +272,7 @@ def invalidate_formsemestre( # was inval_cache(formsemestre_id=None, pdfonly=Fa
SemBulletinsPDFCache.invalidate_sems(formsemestre_ids)
class DefferedSemCacheManager:
class DeferredSemCacheManager:
"""Contexte pour effectuer des opérations indépendantes dans la
même requete qui invalident le cache. Par exemple, quand on inscrit
des étudiants un par un à un semestre, chaque inscription va invalider

View File

@ -70,7 +70,8 @@ class Permission(object):
setattr(Permission, symbol, perm)
Permission.description[symbol] = description
Permission.permission_by_name[symbol] = perm
Permission.NBITS = len(_SCO_PERMISSIONS)
max_perm = max(p[0] for p in _SCO_PERMISSIONS)
Permission.NBITS = max_perm.bit_length()
@staticmethod
def get_by_name(permission_name: str) -> int:

View File

@ -252,7 +252,7 @@ def formsemestre_synchro_etuds(
etudids_a_desinscrire = [nip2etudid(x) for x in a_desinscrire]
etudids_a_desinscrire += a_desinscrire_without_key
#
with sco_cache.DefferedSemCacheManager():
with sco_cache.DeferredSemCacheManager():
do_import_etuds_from_portal(sem, a_importer, etudsapo_ident)
sco_inscr_passage.do_inscrit(sem, etudids_a_inscrire)
sco_inscr_passage.do_desinscrit(sem, etudids_a_desinscrire)

View File

@ -13,7 +13,7 @@ class Config:
SQLALCHEMY_DATABASE_URI = None # set in subclass
FLASK_ENV = None # # set in subclass
SECRET_KEY = os.environ.get("SECRET_KEY") or "90e01e75831e4176a3c70d29564b425f"
SECRET_KEY = os.environ.get("SECRET_KEY") or "90e01e75831e4276a4c70d29564b425f"
SQLALCHEMY_TRACK_MODIFICATIONS = False
LOG_TO_STDOUT = os.environ.get("LOG_TO_STDOUT")
MAIL_SERVER = os.environ.get("MAIL_SERVER", "localhost")
@ -46,6 +46,7 @@ class Config:
class ProdConfig(Config):
"mode production, normalement derrière nginx/gunicorn"
FLASK_ENV = "production"
DEBUG = False
TESTING = False
@ -56,6 +57,7 @@ class ProdConfig(Config):
class DevConfig(Config):
"mode développement"
FLASK_ENV = "development"
DEBUG = True
TESTING = False
@ -66,6 +68,7 @@ class DevConfig(Config):
class TestConfig(DevConfig):
"Pour les tests unitaires"
TESTING = True
DEBUG = True
SQLALCHEMY_DATABASE_URI = (
@ -76,6 +79,19 @@ class TestConfig(DevConfig):
SECRET_KEY = os.environ.get("TEST_SECRET_KEY") or "c7ecff5db1594c208f573ff30e0f6bca"
class TestAPIConfig(Config):
"Pour les tests de l'API"
FLASK_ENV = "test_api"
TESTING = False
DEBUG = True
SQLALCHEMY_DATABASE_URI = (
os.environ.get("SCODOC_TEST_API_DATABASE_URI")
or "postgresql:///SCODOC_TEST_API"
)
DEPT_TEST = "TAPI_" # nom du département, ne pas l'utiliser pour un "vrai"
SECRET_KEY = os.environ.get("TEST_SECRET_KEY") or "c7ecff5db15946789Hhahbh88aja175"
mode = os.environ.get("FLASK_ENV", "production")
if mode == "production":
RunningConfig = ProdConfig
@ -83,3 +99,5 @@ elif mode == "development":
RunningConfig = DevConfig
elif mode == "test":
RunningConfig = TestConfig
elif mode == "test_api":
RunningConfig = TestAPIConfig

View File

@ -496,12 +496,11 @@ def clear_cache(sanitize): # clear-cache
@app.cli.command()
def init_test_database():
def init_test_database(): # init-test-database
"""Initialise les objets en base pour les tests API
(à appliquer sur SCODOC_TEST ou SCODOC_DEV)
"""
click.echo("Initialisation base de test API...")
# import app as mapp # le package app
ctx = app.test_request_context()
ctx.push()

11
tests/api/dotenv_exemple Normal file
View File

@ -0,0 +1,11 @@
# Configuration du _client_ test API
# A renommer .env
# and /opt/scodoc/tests/api/
# et à remplir.
# URL du serveur ScoDoc à interroger
SCODOC_URL = "http://localhost:5000/"
# Le client (python) doit-il vérifier le certificat SSL du serveur ?
# ou True si serveur de production avec certif SSL valide
CHECK_CERTIFICATE = False

View File

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
"""Test Logos
"""Test API
Utilisation :
créer les variables d'environnement: (indiquer les valeurs
pour le serveur ScoDoc que vous voulez interroger)
export SCODOC_URL="https://scodoc.xxx.net/"
export SCODOC_USER="xxx"
export API_USER="xxx"
export SCODOC_PASSWD="xxx"
export CHECK_CERTIFICATE=0 # ou 1 si serveur de production avec certif SSL valide
@ -15,23 +15,25 @@ Utilisation :
"""
import os
import requests
from dotenv import load_dotenv
import pytest
BASEDIR = "/opt/scodoc/tests/api"
load_dotenv(os.path.join(BASEDIR, ".env"))
CHECK_CERTIFICATE = bool(os.environ.get("CHECK_CERTIFICATE", False))
SCODOC_URL = os.environ["SCODOC_URL"]
API_URL = SCODOC_URL + "/ScoDoc/api"
API_USER = os.environ.get("API_USER", "test")
API_PASSWORD = os.environ.get("API_PASSWD", "test")
print(f"SCODOC_URL={SCODOC_URL}")
print(f"API URL={API_URL}")
SCODOC_USER = "test"
SCODOC_PASSWORD = "test"
SCODOC_URL = "http://192.168.1.12:5000"
CHECK_CERTIFICATE = bool(int(os.environ.get("CHECK_CERTIFICATE", False)))
def get_token():
@pytest.fixture
def api_headers() -> dict:
"""
Permet de set le token dans le header
Demande un jeton et renvoie un dict à utiliser dans les en-têtes de requêtes http
"""
r0 = requests.post(
SCODOC_URL + "/ScoDoc/api/tokens", auth=(SCODOC_USER, SCODOC_PASSWORD)
)
r0 = requests.post(API_URL + "/tokens", auth=(API_USER, API_PASSWORD))
token = r0.json()["token"]
return {"Authorization": f"Bearer {token}"}
HEADERS = get_token()

View File

@ -18,99 +18,78 @@ Utilisation :
"""
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.tools_test_api import verify_fields
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
# Etudiant pour les tests
ETUDID = 1
INE = "1"
NIP = "1"
# absences
def test_absences():
fields = ["jour", "matin", "estabs", "estjust", "description", "begin", "end"]
def test_absences(api_headers):
"""
Route: /absences/etudid/<int:etudid>
"""
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/etudid/1",
headers=HEADERS,
f"{API_URL}/absences/etudid/{ETUDID}",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
abs = r.json()[0]
fields_OK = verify_fields(abs, fields)
assert r.status_code == 200
assert fields_OK is True
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/nip/1",
headers=HEADERS,
f"{API_URL}/absences/nip/{NIP}",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
abs = r.json()[0]
fields_OK = verify_fields(abs, fields)
assert r.status_code == 200
assert fields_OK is True
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/ine/1",
headers=HEADERS,
f"{API_URL}/absences/ine/{INE}",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
abs = r.json()[0]
fields_OK = verify_fields(abs, fields)
assert r.status_code == 200
assert fields_OK is True
# absences_justify
def test_absences_justify():
fields = ["jour", "matin", "estabs", "estjust", "description", "begin", "end"]
def test_absences_justify(api_headers):
"""
Route: /absences/etudid/<etudid:int>/just
"""
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/etudid/1/just",
headers=HEADERS,
API_URL + f"/absences/etudid/{ETUDID}/just",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
abs = r.json()[0]
fields_OK = verify_fields(abs, fields)
assert r.status_code == 200
assert fields_OK is True
# TODO vérifier résultat
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/nip/1/just",
headers=HEADERS,
API_URL + f"/absences/nip/{NIP}/just",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
abs = r.json()[0]
fields_OK = verify_fields(abs, fields)
assert r.status_code == 200
assert fields_OK is True
# TODO vérifier résultat
r = requests.get(
SCODOC_URL + "/ScoDoc/api/absences/ine/1/just",
headers=HEADERS,
API_URL + f"/absences/ine/{INE}/just",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
abs = r.json()[0]
fields_OK = verify_fields(abs, fields)
assert r.status_code == 200
assert fields_OK is True
# TODO vérifier résultat
# abs_groupe_etat
# def test_abs_groupe_etat():
# XXX TODO
# def test_abs_groupe_etat(api_headers):
# """
# Route:
# """
# r = requests.get(
# SCODOC_URL
# + "/ScoDoc/api/absences/abs_group_etat/?group_id=<int:group_id>&date_debut=date_debut&date_fin=date_fin",
# headers=HEADERS,
# API_URL + "/absences/abs_group_etat/?group_id=<int:group_id>&date_debut=date_debut&date_fin=date_fin",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200

View File

@ -19,11 +19,12 @@ Utilisation :
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
# departements
def test_departements():
def test_departements(api_headers):
"check liste de sdépartements"
fields = [
"id",
"acronym",
@ -33,8 +34,8 @@ def test_departements():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/departements",
headers=HEADERS,
API_URL + "/departements",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
@ -47,9 +48,8 @@ def test_departements():
assert fields_OK is True
# liste_etudiants
def test_liste_etudiants():
fields = [
def test_list_etudiants(api_headers):
fields = {
"civilite",
"code_ine",
"code_nip",
@ -74,11 +74,11 @@ def test_liste_etudiants():
"telephone",
"fax",
"description",
]
}
r = requests.get(
SCODOC_URL + "/ScoDoc/api/departements/TAPI/etudiants/list",
headers=HEADERS,
API_URL + "/departements/TAPI/etudiants/list",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
@ -91,8 +91,8 @@ def test_liste_etudiants():
assert fields_OK is True
r = requests.get(
SCODOC_URL + "/ScoDoc/api/departements/TAPI/etudiants/list/1",
headers=HEADERS,
API_URL + "/departements/TAPI/etudiants/list/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
@ -106,7 +106,7 @@ def test_liste_etudiants():
# liste_semestres_courant
def test_semestres_courant():
def test_semestres_courant(api_headers):
fields = [
"titre",
"gestion_semestrielle",
@ -136,8 +136,8 @@ def test_semestres_courant():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/departements/TAPI/semestres_courants",
headers=HEADERS,
API_URL + "/departements/TAPI/semestres_courants",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
@ -148,14 +148,3 @@ def test_semestres_courant():
assert r.status_code == 200
assert len(r.json()) == 1
assert fields_OK is True
# referenciel_competences
def test_referenciel_competences():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/departements/TAPI/formations/1/referentiel_competences",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200 or 204

View File

@ -20,12 +20,14 @@ from random import randint
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
# etudiants_courant
def test_etudiants_courant():
def test_etudiants_courant(api_headers):
"""
Route: /etudiants/courant
"""
fields = [
"id",
"nip",
@ -36,19 +38,19 @@ def test_etudiants_courant():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiants/courant",
headers=HEADERS,
API_URL + "/etudiants/courant",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 16
etudiants = r.json()
assert len(etudiants) == 16 # XXX HARDCODED
# Choisis aléatoirement un étudiant dans la liste des étudiants
etu = r.json()[randint(0, len(r.json())) - 1]
etud = etudiants[-1]
fields_OK = verify_fields(etu, fields)
fields_ok = verify_fields(etud, fields)
assert fields_OK is True
assert fields_ok is True
########## Version long ################
@ -80,24 +82,24 @@ def test_etudiants_courant():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiants/courant/long",
headers=HEADERS,
API_URL + "/etudiants/courant/long",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 16
etudiants = r.json()
assert len(etudiants) == 16 # HARDCODED
# Choisis aléatoirement un étudiant dans la liste des étudiants
etu = r.json()[randint(0, len(r.json())) - 1]
etud = etudiants[-1]
fields_ok = verify_fields(etud, fields_long)
fields_OK = verify_fields(etu, fields_long)
assert fields_OK is True
assert fields_ok is True
# etudiant
def test_etudiant():
def test_etudiant(api_headers):
"""
Route:
"""
fields = [
"civilite",
"code_ine",
@ -126,57 +128,49 @@ def test_etudiant():
]
######### Test etudid #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/etudid/1",
headers=HEADERS,
API_URL + "/etudiant/etudid/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 24
etud = r.json()
assert len(etud) == 24 # ? HARDCODED
etu = r.json()
fields_OK = verify_fields(etu, fields)
assert fields_OK is True
fields_ok = verify_fields(etud, fields)
assert fields_ok is True
######### Test code nip #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/nip/1",
headers=HEADERS,
API_URL + "/etudiant/nip/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 24
etu = r.json()
fields_OK = verify_fields(etu, fields)
assert fields_OK is True
etud = r.json()
assert len(etud) == 24
fields_ok = verify_fields(etud, fields)
assert fields_ok is True
######### Test code ine #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/ine/1",
headers=HEADERS,
API_URL + "/etudiant/ine/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 24
etu = r.json()
fields_OK = verify_fields(etu, fields)
assert fields_OK is True
etud = r.json()
assert len(etud) == 24
fields_ok = verify_fields(etud, fields)
assert fields_ok is True
# etudiant_formsemestres
def test_etudiant_formsemestres():
def test_etudiant_formsemestres(api_headers):
"""
Route: /etudiant/etudid/<etudid:int>/formsemestres
"""
fields = [
"date_fin",
"resp_can_edit",
@ -208,89 +202,92 @@ def test_etudiant_formsemestres():
######### Test etudid #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/etudid/1/formsemestres",
headers=HEADERS,
API_URL + "/etudiant/etudid/1/formsemestres",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 1
formsemestres = r.json()
assert len(formsemestres) == 1
formsemestre = r.json()[0]
formsemestre = formsemestres[0]
fields_OK = verify_fields(formsemestre, fields)
assert fields_OK is True
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
######### Test code nip #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/nip/1/formsemestres",
headers=HEADERS,
API_URL + "/etudiant/nip/1/formsemestres",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 1
formsemestres = r.json()
assert len(formsemestres) == 1
formsemestre = r.json()[0]
formsemestre = formsemestres[0]
fields_OK = verify_fields(formsemestre, fields)
assert fields_OK is True
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
######### Test code ine #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/ine/1/formsemestres",
headers=HEADERS,
API_URL + "/etudiant/ine/1/formsemestres",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 1
formsemestres = r.json()
assert len(formsemestres) == 1
formsemestre = r.json()[0]
formsemestre = formsemestres[0]
fields_OK = verify_fields(formsemestre, fields)
assert fields_OK is True
fields_ok = verify_fields(formsemestre, fields)
assert fields_ok is True
# etudiant_bulletin_semestre
def test_etudiant_bulletin_semestre():
def test_etudiant_bulletin_semestre(api_headers):
"""
Route: /etudiant/etudid/<etudid>/formsemestre/<formsemestre_id>/bulletin
"""
######### Test etudid #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/etudid/1/formsemestre/1/bulletin",
headers=HEADERS,
API_URL + "/etudiant/etudid/1/formsemestre/1/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 13
bul = r.json()
assert len(bul) == 13 # HARDCODED
######### Test code nip #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/nip/1/formsemestre/1/bulletin",
headers=HEADERS,
API_URL + "/etudiant/nip/1/formsemestre/1/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 13
bul = r.json()
assert len(bul) == 13 # HARDCODED
######### Test code ine #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/ine/1/formsemestre/1/bulletin",
headers=HEADERS,
API_URL + "/etudiant/ine/1/formsemestre/1/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 13
bul = r.json()
assert len(bul) == 13 # HARDCODED
# etudiant_groups
def test_etudiant_groups():
def test_etudiant_groups(api_headers):
"""
Route:
/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/groups
"""
fields = [
"partition_id",
"id",
@ -306,47 +303,39 @@ def test_etudiant_groups():
######### Test etudid #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/etudid/1/semestre/1/groups",
headers=HEADERS,
API_URL + "/etudiant/etudid/1/formsemestre/1/groups",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 1
groups = r.json()[0]
fields_OK = verify_fields(groups, fields)
assert fields_OK is True
groups = r.json()
assert len(groups) == 1 # dans un seul groupe
group = groups[0]
fields_ok = verify_fields(group, fields)
assert fields_ok is True
######### Test code nip #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/nip/1/semestre/1/groups",
headers=HEADERS,
API_URL + "/etudiant/nip/1/formsemestre/1/groups",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 1
groups = r.json()[0]
fields_OK = verify_fields(groups, fields)
assert fields_OK is True
groups = r.json()
assert len(groups) == 1 # dans un seul groupe
group = groups[0]
fields_ok = verify_fields(group, fields)
assert fields_ok is True
######### Test code ine #########
r = requests.get(
SCODOC_URL + "/ScoDoc/api/etudiant/ine/1/semestre/1/groups",
headers=HEADERS,
API_URL + "/etudiant/ine/1/formsemestre/1/groups",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
assert len(r.json()) == 1
groups = r.json()[0]
fields_OK = verify_fields(groups, fields)
assert fields_OK is True
groups = r.json()
assert len(groups) == 1 # dans un seul groupe
group = groups[0]
fields_ok = verify_fields(group, fields)
assert fields_ok is True

View File

@ -19,53 +19,31 @@ Utilisation :
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.tools_test_api import verify_fields
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
# evaluations
def test_evaluations():
fields = [
"moduleimpl_id",
"jour",
"heure_debut",
"description",
"coefficient",
"publish_incomplete",
"numero",
"id",
"heure_fin",
"note_max",
"visibulletin",
"evaluation_type",
"evaluation_id",
"jouriso",
"duree",
"descrheure",
"matin",
"apresmidi",
]
def test_evaluations(api_headers):
"""
Route: /evaluation/<int:moduleimpl_id>
"""
r = requests.get(
SCODOC_URL + "/ScoDoc/api/evaluations/1",
headers=HEADERS,
verify=CHECK_CERTIFICATE,
)
eval = r.json()[0]
fields_OK = verify_fields(eval, fields)
assert r.status_code == 200
# assert len(r.json()) == 1
assert fields_OK is True
# evaluation_notes
def test_evaluation_notes():
r = requests.get(
SCODOC_URL + "/ScoDoc/api/evaluations/eval_notes/1",
headers=HEADERS,
API_URL + "/evaluations/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# TODO
# TODO car pas d'évaluations créées à ce stade
# def test_evaluation_notes(api_headers):
# """
# Route: /evaluation/eval_notes/<int:evaluation_id>
# """
# r = requests.get(
# API_URL + "/evaluation/eval_notes/1",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
# # TODO

View File

@ -19,43 +19,33 @@ Utilisation :
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
# formations
def test_formations():
fields = [
"id",
"acronyme",
"titre_officiel",
"formation_code",
"code_specialite",
"dept_id",
"titre",
"version",
"type_parcours",
"referentiel_competence_id",
"formation_id",
]
def test_formations_ids(api_headers):
"""
Route: /formations_ids
"""
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formations",
headers=HEADERS,
API_URL + "/formations_ids",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
formation = r.json()[0]
fields_OK = verify_fields(formation, fields)
assert r.status_code == 200
assert len(r.json()) == 1
assert fields_OK is True
formations_ids = r.json()
# Une liste non vide d'entiers
assert isinstance(formations_ids, list)
assert len(formations_ids) > 0
assert all(isinstance(x, int) for x in formations_ids)
# formations_by_id
def test_formations_by_id():
def test_formations_by_id(api_headers):
"""
Route: /formations/<int:formation_id>
"""
fields = [
"id",
"acronyme",
@ -71,21 +61,22 @@ def test_formations_by_id():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formations/1",
headers=HEADERS,
API_URL + "/formations/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
formation = r.json()
fields_OK = verify_fields(formation, fields)
assert r.status_code == 200
assert fields_OK is True
fields_ok = verify_fields(formation, fields)
assert fields_ok is True
# TODO tester le contenu de certains champs
# formation_export_by_formation_id
def test_formation_export_by_formation_id():
def test_formation_export(api_headers):
"""
Route: /formations/formation_export/<int:formation_id>
"""
fields = [
"id",
"acronyme",
@ -101,32 +92,33 @@ def test_formation_export_by_formation_id():
"ue",
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formations/formation_export/1",
headers=HEADERS,
API_URL + "/formations/formation_export/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
export_formation = r.json()
fields_OK = verify_fields(export_formation, fields)
assert r.status_code == 200
assert fields_OK is True
fields_ok = verify_fields(export_formation, fields)
assert fields_ok is True
# TODO tester le contenu de certains champs
# formsemestre_apo
# def test_formsemestre_apo():
# TODO
# def test_formsemestre_apo(api_headers):
# r = requests.get(
# SCODOC_URL + "/ScoDoc/api/formations/apo/<string:etape_apo>",
# headers=HEADERS,
# API_URL + "/formations/apo/<string:etape_apo>",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
# moduleimpl
def test_moduleimpl():
def test_moduleimpl(api_headers):
"""
Route: /formations/moduleimpl/<int:moduleimpl_id>
"""
fields = [
"id",
"formsemestre_id",
@ -139,22 +131,22 @@ def test_moduleimpl():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formations/moduleimpl/1",
headers=HEADERS,
API_URL + "/formations/moduleimpl/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
moduleimpl = r.json()
fields_OK = verify_fields(moduleimpl, fields)
assert r.status_code == 200
assert fields_OK is True
fields_ok = verify_fields(moduleimpl, fields)
assert fields_ok is True
# TODO tester le contenu de certains champs
# moduleimpls_sem
def test_moduleimpls_sem():
def test_moduleimpls_sem(api_headers):
"""
Route: /formations/moduleimpl/formsemestre/<int:formsemestre_id>/list
"""
fields = [
"id",
"formsemestre_id",
@ -168,14 +160,27 @@ def test_moduleimpls_sem():
"ens",
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formations/moduleimpl/formsemestre/1/list",
headers=HEADERS,
API_URL + "/formations/moduleimpl/formsemestre/1/list",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
moduleimpl = r.json()[0]
fields_OK = verify_fields(moduleimpl, fields)
assert r.status_code == 200
assert len(r.json()) == 21
assert fields_OK is True
moduleimpls = r.json()
moduleimpl = moduleimpls[0]
fields_ok = verify_fields(moduleimpl, fields)
assert len(moduleimpls) == 21 # XXX HARDCODED !
assert fields_ok is True
def test_referentiel_competences(api_headers):
"""
Route: "/formations/<int:formation_id>/referentiel_competences",
"""
r = requests.get(
API_URL + "/formations/1/referentiel_competences",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# XXX A compléter

View File

@ -19,14 +19,17 @@ Utilisation :
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
# formsemestre
def test_formsemestre():
def test_formsemestre(api_headers):
"""
Route:
"""
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formsemestre/1",
headers=HEADERS,
API_URL + "/formsemestre/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
@ -61,40 +64,44 @@ def test_formsemestre():
"responsables",
]
fields_OK = verify_fields(formsemestre, fields)
fields_ok = verify_fields(formsemestre, fields)
assert fields_OK is True
assert fields_ok is True
# etudiant_bulletin
def test_etudiant_bulletin():
def test_etudiant_bulletin(api_headers):
"""
Route:
"""
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formsemestre/1/etudiant/etudid/1/bulletin",
headers=HEADERS,
API_URL + "/formsemestre/1/etudiant/etudid/1/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formsemestre/1/etudiant/nip/1/bulletin",
headers=HEADERS,
API_URL + "/formsemestre/1/etudiant/nip/1/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formsemestre/1/etudiant/ine/1/bulletin",
headers=HEADERS,
API_URL + "/formsemestre/1/etudiant/ine/1/bulletin",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# bulletins
def test_bulletins():
def test_bulletins(api_headers):
"""
Route:
"""
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formsemestre/1/bulletins",
headers=HEADERS,
API_URL + "/formsemestre/1/bulletins",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
@ -103,15 +110,17 @@ def test_bulletins():
# # jury
# def test_jury():
# r = requests.get(
# SCODOC_URL + "/ScoDoc/api/formsemestre/1/jury",
# headers=HEADERS,
# API_URL + "/formsemestre/1/jury",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
# semestre_index
def test_semestre_index():
# TODO A revoir
def test_semestre_index(api_headers):
"""
Route: TODO
"""
ue_fields = [
"semestre_idx",
"type",
@ -170,8 +179,8 @@ def test_semestre_index():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/formsemestre/1/programme",
headers=HEADERS,
API_URL + "/formsemestre/1/programme",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200

View File

@ -19,37 +19,41 @@ Utilisation :
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
# jury_preparation
def test_jury_preparation():
def test_jury_preparation(api_headers):
"""
Route:
"""
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/jury/formsemestre/<int:formsemestre_id>/preparation_jury",
headers=HEADERS,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# jury_decisions
def test_jury_decisions():
def test_jury_decisions(api_headers):
"""
Route:
"""
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/jury/formsemestre/<int:formsemestre_id>/decisions_jury",
headers=HEADERS,
API_URL + "/jury/formsemestre/<int:formsemestre_id>/decisions_jury",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# set_decision_jury
def test_set_decision_jury():
def test_set_decision_jury(api_headers):
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/jury/set_decision/etudid?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>",
headers=HEADERS,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
@ -58,7 +62,7 @@ def test_set_decision_jury():
SCODOC_URL
+ "/ScoDoc/api/jury/set_decision/nip?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>",
headers=HEADERS,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
@ -67,18 +71,20 @@ def test_set_decision_jury():
SCODOC_URL
+ "/ScoDoc/api/jury/set_decision/ine?etudid=<int:etudid>&formsemestre_id=<int:formesemestre_id>"
"&jury=<string:decision_jury>&devenir=<string:devenir_jury>&assiduite=<bool>",
headers=HEADERS,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# annule_decision_jury
def test_annule_decision_jury():
def test_annule_decision_jury(api_headers):
"""
Route:
"""
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/jury/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/annule_decision",
headers=HEADERS,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
@ -86,7 +92,7 @@ def test_annule_decision_jury():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/jury/nip/<int:nip>/formsemestre/<int:formsemestre_id>/annule_decision",
headers=HEADERS,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
@ -94,7 +100,7 @@ def test_annule_decision_jury():
r = requests.get(
SCODOC_URL
+ "/ScoDoc/api/jury/ine/<int:ine>/formsemestre/<int:formsemestre_id>/annule_decision",
headers=HEADERS,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200

View File

@ -5,11 +5,16 @@
"""Exemple utilisation API ScoDoc 9 avec jeton obtenu par basic authentication
utilisation:
à faire fonctionner en environnment de test (FLASK_ENV=test dans le fichier .env)
à faire fonctionner en environnment de test (FLASK_ENV=test_api dans le fichier .env)
pytest tests/api/test_api_logos.py
"""
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
# XXX TODO
# Ce test a une logique très différente des autres : A UNIFIER
from tests.api.setup_test_api import API_URL
from scodoc import app
from tests.unit.config_test_logos import (
@ -22,35 +27,47 @@ from tests.unit.config_test_logos import (
def test_super_access(create_super_token):
"""
Route:
"""
dept1, dept2, dept3, token = create_super_token
HEADERS = {"Authorization": f"Bearer {token}"}
headers = {"Authorization": f"Bearer {token}"}
with app.test_client() as client:
response = client.get("/ScoDoc/api/logos", headers=HEADERS)
response = client.get(API_URL + "/logos", headers=headers)
assert response.status_code == 200
assert response.json is not None
def test_admin_access(create_admin_token):
"""
Route:
"""
dept1, dept2, dept3, token = create_admin_token
headers = {"Authorization": f"Bearer {token}"}
with app.test_client() as client:
response = client.get("/ScoDoc/api/logos", headers=headers)
response = client.get(API_URL + "/logos", headers=headers)
assert response.status_code == 401
def test_lambda_access(create_lambda_token):
"""
Route:
"""
dept1, dept2, dept3, token = create_lambda_token
headers = {"Authorization": f"Bearer {token}"}
with app.test_client() as client:
response = client.get("/ScoDoc/api/logos", headers=headers)
response = client.get(API_URL + "/logos", headers=headers)
assert response.status_code == 401
def test_initial_with_header_and_footer(create_super_token):
"""
Route:
"""
dept1, dept2, dept3, token = create_super_token
headers = {"Authorization": f"Bearer {token}"}
with app.test_client() as client:
response = client.get("/ScoDoc/api/logos", headers=headers)
response = client.get(API_URL + "/logos", headers=headers)
assert response.status_code == 200
assert response.json is not None
assert len(response.json) == 7

View File

@ -19,12 +19,14 @@ Utilisation :
import requests
from tests.api.setup_test_api import SCODOC_URL, CHECK_CERTIFICATE, HEADERS
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
# partition
def test_partition():
def test_partition(api_headers):
"""
Route:
"""
fields = [
"partition_id",
"id",
@ -36,23 +38,22 @@ def test_partition():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/partitions/1",
headers=HEADERS,
API_URL + "/partitions/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
partition = r.json()[0]
fields_OK = verify_fields(partition, fields)
assert r.status_code == 200
assert len(r.json()) == 2
assert fields_OK is True
partitions = r.json()
assert len(partitions) == 1
partition = partitions[0]
fields_ok = verify_fields(partition, fields)
assert fields_ok is True
# etud_in_group
def test_etud_in_group():
def test_etud_in_group(api_headers):
"""
Route:
"""
fields = [
"etudid",
"id",
@ -92,33 +93,36 @@ def test_etud_in_group():
]
r = requests.get(
SCODOC_URL + "/ScoDoc/api/partitions/groups/1",
headers=HEADERS,
API_URL + "/partitions/groups/1",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
etu = r.json()[0]
fields_OK = verify_fields(etu, fields)
fields_ok = verify_fields(etu, fields)
assert r.status_code == 200
assert len(r.json()) == 16
assert fields_OK is True
assert fields_ok is True
# r = requests.get(
# SCODOC_URL + "/ScoDoc/api/partitions/groups/1/etat/<string:etat>",
# headers=HEADERS,
# API_URL + "/partitions/groups/1/etat/<string:etat>",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
# # set_groups
# def test_set_groups():
# def test_set_groups(api_headers):
# """
# Route:
# """
# r = requests.get(
# SCODOC_URL
# + "/partitions/set_groups/partition/<int:partition_id>/groups/<string:groups_id>"
# "/delete/<string:groups_to_delete>/create/<string:groups_to_create>",
# headers=HEADERS,
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200

View File

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
"""Test permissions
On a deux utilisateurs dans la base test API:
- "test", avec le rôle LecteurAPI qui a APIView,
- et "other", qui n'a aucune permission.
Lancer :
pytest tests/api/test_api_permissions.py
"""
import requests
import flask
from tests.api.setup_test_api import API_URL, SCODOC_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
from app import create_app
from config import RunningConfig
def test_permissions(api_headers):
"""
vérification de la permissions APIView et du non accès sans role
de toutes les routes de l'API
"""
# Ce test va récupérer toutes les routes de l'API
app = create_app(RunningConfig)
assert app
# Les routes de l'API avec GET, excluant les logos pour le momeent XXX
api_rules = [
r
for r in app.url_map.iter_rules()
if str(r).startswith("/ScoDoc/api")
and not "logo" in str(r) # ignore logos
and "GET" in r.methods
]
assert len(api_rules) > 0
args = {
"etudid": 1,
# "date_debut":
# "date_fin":
"dept": "TAPI",
"etape_apo": "???",
"etat": "I",
"evaluation_id": 1,
"formation_id": 1,
"formsemestre_id": 1,
"group_id": 1,
"ine": "1",
"module_id": 1,
"moduleimpl_id": 1,
"nip": 1,
"partition_id": 1,
}
for rule in api_rules:
path = rule.build(args)[1]
if not "GET" in rule.methods:
# skip all POST routes
continue
r = requests.get(
SCODOC_URL + path,
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
# Même chose sans le jeton:
for rule in api_rules:
path = rule.build(args)[1]
if not "GET" in rule.methods:
# skip all POST routes
continue
r = requests.get(
SCODOC_URL + path,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 401
# Demande un jeton pour "other"
r = requests.post(API_URL + "/tokens", auth=("other", "other"))
assert r.status_code == 200
token = r.json()["token"]
headers = {"Authorization": f"Bearer {token}"}
# Vérifie que tout est interdit
for rule in api_rules:
path = rule.build(args)[1]
if not "GET" in rule.methods:
# skip all POST routes
continue
r = requests.get(
SCODOC_URL + path,
headers=headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 403

View File

@ -1,9 +1,13 @@
def verify_fields(json_response, fields):
"""Utilitaires pour les tests de l'API
"""
Vérifie si les champs de la réponse json sont corrects
def verify_fields(json_response: dict, fields: set) -> bool:
"""
Vérifie si les champs attendu de la réponse json sont présents
json_response : la réponse de la requête
fields : une liste avec l'ensemble des champs à vérifier
fields : ensemble des champs à vérifier
Retourne True ou False
"""

View File

@ -9,8 +9,16 @@ die() {
echo
exit 1
}
[ $# = 1 ] || die "Usage $0 db_name"
[ $# = 1 ] || [ $# = 2 ] || die "Usage $0 [--drop] db_name"
if [ "$1" = "--drop" ]
then
db_name="$2"
echo "Dropping database $db_name..."
dropdb "$db_name"
else
db_name="$1"
fi
# Le répertoire de ce script:
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

View File

@ -5,60 +5,59 @@
Création des départements, formations, semestres, étudiants, groupes...
utilisation:
1) modifier le .env pour indiquer
SCODOC_DATABASE_URI="postgresql:///SCO_TEST_API"
1) modifier /opt/scodoc/.env pour indiquer
FLASK_ENV=test_api
FLASK_DEBUG=1
2) En tant qu'utilisateur scodoc, lancer:
tools/create_database.sh SCO_TEST_API
tools/create_database.sh SCODOC_TEST_API
flask db upgrade
flask sco-db-init --erase
flask init-test-database
flask user-role -a Admin -d TAPI test
flask user-password test
flask create-role APIUserViewer
flask edit-role APIUserViewer -a APIView
flask user-role test -a APIUserViewer
3) relancer ScoDoc:
flask run --host 0.0.0.0
4) lancer client de test (ou vérifier dans le navigateur)
4) lancer client de test
"""
import datetime
import random
import sys
random.seed(12345678) # tests reproductibles
from flask_login import login_user
from app import auth
from app.auth.models import Role, User
from app import models
from app.models import Departement, Formation, FormSemestre
from app import db
from app.scodoc import (
sco_cache,
sco_evaluation_db,
sco_formations,
sco_formsemestre,
sco_formsemestre_inscriptions,
sco_groups,
)
from app.scodoc.sco_permissions import Permission
from tools.fakeportal.gen_nomprenoms import nomprenom
random.seed(12345678) # tests reproductibles
# La formation à utiliser:
FORMATION_XML_FILENAME = "tests/ressources/formations/scodoc_formation_RT_BUT_RT_v1.xml"
def init_departement(acronym):
def init_departement(acronym: str) -> Departement:
"Create dept, and switch context into it."
import app as mapp
dept = models.Departement(acronym=acronym)
dept = Departement(acronym=acronym)
db.session.add(dept)
mapp.set_sco_dept(acronym)
db.session.commit()
return dept
def import_formation() -> models.Formation:
def import_formation() -> Formation:
"""Import formation from XML.
Returns formation_id
"""
@ -66,20 +65,37 @@ def import_formation() -> models.Formation:
doc = f.read()
# --- Création de la formation
f = sco_formations.formation_import_xml(doc)
return models.Formation.query.get(f[0])
return Formation.query.get(f[0])
def create_user(dept):
"""créé les utilisaterurs nécessaires aux tests"""
user = auth.models.User(
user_name="test", nom="Doe", prenom="John", dept=dept.acronym
)
def create_users(dept: Departement) -> tuple:
"""créé les utilisateurs nécessaires aux tests"""
# Un utilisateur "test" (passwd test) pouvant lire l'API
user = User(user_name="test", nom="Doe", prenom="John", dept=dept.acronym)
user.set_password("test")
db.session.add(user)
# Le rôle standard LecteurAPI existe déjà
role = Role.query.filter_by(name="LecteurAPI").first()
if role is None:
print("Erreur: rôle LecteurAPI non existant")
sys.exit(1)
perm_api_view = Permission.get_by_name("APIView")
role.add_permission(perm_api_view)
db.session.add(role)
user.add_role(role, None)
# Un utilisateur "other" n'ayant aucune permission sur l'API
other = User(user_name="other", nom="Sans", prenom="Permission", dept=dept.acronym)
other.set_password("other")
db.session.add(other)
db.session.commit()
return user
return user, other
def create_fake_etud(dept):
def create_fake_etud(dept: Departement) -> models.Identite:
"""Créé un faux étudiant et l'insère dans la base"""
civilite = random.choice(("M", "F", "X"))
nom, prenom = nomprenom(civilite)
@ -100,14 +116,18 @@ def create_fake_etud(dept):
return etud
def create_etuds(dept, nb=16):
def create_etuds(dept: Departement, nb=16) -> list:
"create nb etuds"
return [create_fake_etud(dept) for _ in range(nb)]
def create_formsemestre(formation, user, semestre_idx=1):
"""Create formsemestre and moduleimpls"""
formsemestre = models.FormSemestre(
def create_formsemestre(
formation: Formation, responsable: User, semestre_idx=1
) -> FormSemestre:
"""Create formsemestre and moduleimpls
responsable: resp. du formsemestre
"""
formsemestre = FormSemestre(
dept_id=formation.dept_id,
semestre_id=semestre_idx,
titre="Semestre test",
@ -121,7 +141,9 @@ def create_formsemestre(formation, user, semestre_idx=1):
# Crée un modulimpl par module de ce semestre:
for module in formation.modules.filter_by(semestre_id=semestre_idx):
modimpl = models.ModuleImpl(
module_id=module.id, formsemestre_id=formsemestre.id, responsable_id=user.id
module_id=module.id,
formsemestre_id=formsemestre.id,
responsable_id=responsable.id,
)
db.session.add(modimpl)
db.session.commit()
@ -132,7 +154,7 @@ def create_formsemestre(formation, user, semestre_idx=1):
return formsemestre
def inscrit_etudiants(etuds, formsemestre):
def inscrit_etudiants(etuds: list, formsemestre: FormSemestre):
"""Inscrit les etudiants aux semestres et à tous ses modules"""
for etud in etuds:
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
@ -144,13 +166,37 @@ def inscrit_etudiants(etuds, formsemestre):
)
def init_test_database():
def create_evaluations(formsemestre: FormSemestre):
"creation d'une evaluation dans cahque modimpl du semestre"
for modimpl in formsemestre.modimpls:
args = {
"moduleimpl_id": modimpl.id,
"jour": None,
"heure_debut": "8h00",
"heure_fin": "9h00",
"description": None,
"note_max": 20,
"coefficient": 1.0,
"visibulletin": True,
"publish_incomplete": True,
"evaluation_type": None,
"numero": None,
}
evaluation_id = sco_evaluation_db.do_evaluation_create(**args)
def init_test_database():
"""Appelé par la commande `flask init-test-database`
Création d'un département et de son contenu pour les tests
"""
dept = init_departement("TAPI")
user = create_user(dept)
user_lecteur, user_autre = create_users(dept)
with sco_cache.DeferredSemCacheManager():
etuds = create_etuds(dept)
formation = import_formation()
formsemestre = create_formsemestre(formation, user)
formsemestre = create_formsemestre(formation, user_lecteur)
create_evaluations(formsemestre)
inscrit_etudiants(etuds, formsemestre)
# à compléter
# - groupes