Ajoute un suivi xAPI optionnel (bolt-on) au paquet SCORM exporté
Greffe l'envoi de statements xAPI vers un LRS configurable par le créateur du jeu, en parallèle du reporting SCORM existant : réglages stockés en base (_meta), formulaire dans la modale d'export, injection dans le paquet exporté. Relié aussi bien à l'action de flow "Modifier un score/statut" qu'au parcours quête/quiz (qui alimentait déjà le SCORM classique via un chemin séparé). L'export ne se lance plus automatiquement à l'ouverture de la modale, pour laisser le temps d'enregistrer les réglages xAPI avant de générer le paquet.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""Réglages xAPI (bolt-on, voir db/games/get_xapi_settings.py,
|
||||
routes/publish/xapi_settings.py) — le mot de passe ne doit JAMAIS
|
||||
ressortir en clair (seulement un booléen `password_set`), et un POST
|
||||
sans mot de passe ne doit pas écraser celui déjà enregistré."""
|
||||
from tests.test_auth import anon_client # noqa: F401
|
||||
|
||||
|
||||
def test_xapi_settings_get_defaults_to_empty(client, game):
|
||||
resp = client.get(f"/game/{game}/xapi-settings")
|
||||
assert resp.status_code == 200
|
||||
body = resp.get_json()
|
||||
assert body == {"endpoint": "", "login": "", "password_set": False}
|
||||
|
||||
|
||||
def test_xapi_settings_post_then_get_round_trip(client, game):
|
||||
resp = client.post(f"/game/{game}/xapi-settings", json={
|
||||
"endpoint": "https://lrs.example.com/xapi/",
|
||||
"login": "monlogin",
|
||||
"password": "monmotdepasse",
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
assert resp.get_json() == {"ok": True}
|
||||
|
||||
resp = client.get(f"/game/{game}/xapi-settings")
|
||||
body = resp.get_json()
|
||||
assert body["endpoint"] == "https://lrs.example.com/xapi/"
|
||||
assert body["login"] == "monlogin"
|
||||
assert body["password_set"] is True
|
||||
assert "password" not in body
|
||||
|
||||
|
||||
def test_xapi_settings_post_with_blank_password_keeps_the_existing_one(client, game):
|
||||
client.post(f"/game/{game}/xapi-settings", json={
|
||||
"endpoint": "https://lrs.example.com/xapi/",
|
||||
"login": "monlogin",
|
||||
"password": "monmotdepasse",
|
||||
})
|
||||
|
||||
resp = client.post(f"/game/{game}/xapi-settings", json={
|
||||
"endpoint": "https://lrs.example.com/xapi/v2/",
|
||||
"login": "monlogin",
|
||||
"password": "",
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
|
||||
import db
|
||||
settings = db.get_xapi_settings(game)
|
||||
assert settings["endpoint"] == "https://lrs.example.com/xapi/v2/"
|
||||
assert settings["password"] == "monmotdepasse"
|
||||
|
||||
|
||||
def test_xapi_settings_route_is_isolated_like_other_game_routes(anon_client):
|
||||
"""Même garde d'accès que /game/<slug>/publish (core/auth_guard.py) —
|
||||
aucune vérification supplémentaire écrite pour cette route."""
|
||||
from tests.test_auth import _register, _confirm_2fa, _complete_onboarding, _cleanup_project
|
||||
|
||||
_register(anon_client, "xapisettingsisolation@example.com")
|
||||
_confirm_2fa(anon_client)
|
||||
_complete_onboarding(anon_client)
|
||||
try:
|
||||
resp = anon_client.get("/game/un-projet-qui-nest-pas-le-sien/xapi-settings")
|
||||
assert resp.status_code == 403
|
||||
resp = anon_client.post("/game/un-projet-qui-nest-pas-le-sien/xapi-settings", json={})
|
||||
assert resp.status_code == 403
|
||||
finally:
|
||||
_cleanup_project("xapisettingsisolation@example.com")
|
||||
Reference in New Issue
Block a user