Files
Forge-Engine/tests/test_user_assets.py
T
williamandClaude Sonnet 5 b07b231a61
Build and deploy / test-python (push) Successful in 12m24s
Build and deploy / test-js (push) Successful in 1m9s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Ajoute l'assistant IA "Ruby" (Claude + Scenario) et corrige plusieurs bugs de la scène
Intègre un chat IA capable de manipuler la scène via les mêmes fonctions
que l'éditeur manuel (objets, variables, déclencheurs, images générées),
avec conversations multiples par écran façon Claude. Corrige au passage
le rafraîchissement pjax hors-ordre, l'onglet IA/déclencheurs vide après
sélection d'un objet, la comparaison de booléens dans les conditions, et
le blocage du glisser-déposer hors du cadre caméra après un redimensionnement
de fond par l'IA.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 19:40:31 +02:00

81 lines
3.0 KiB
Python

""""Mes assets" (voir plan Phase 1, §2) — bibliothèque d'images PAR
COMPTE, distincte du dossier d'un jeu (routes/uploads/upload_file.py) :
réutilisable d'un projet à l'autre du MÊME compte, jamais visible par un
autre."""
import io
import auth
def test_create_and_list_user_asset(client):
with client.session_transaction() as sess:
user_id = sess["user_id"]
asset_id = auth.create_user_asset(user_id, "abc123.png", original_name="photo.png", source="upload")
assets = auth.list_user_assets(user_id)
assert any(a["id"] == asset_id and a["filename"] == "abc123.png" for a in assets)
def test_list_user_assets_is_isolated_per_account(client, user_client):
with client.session_transaction() as sess:
admin_id = sess["user_id"]
with user_client.session_transaction() as sess:
user_id = sess["user_id"]
auth.create_user_asset(admin_id, "admin_only.png")
assets = auth.list_user_assets(user_id)
assert all(a["filename"] != "admin_only.png" for a in assets)
def test_get_user_asset_returns_none_for_unknown_id():
assert auth.get_user_asset(999999) is None
def test_delete_user_asset_refuses_when_not_the_owner(client, user_client):
with client.session_transaction() as sess:
admin_id = sess["user_id"]
with user_client.session_transaction() as sess:
user_id = sess["user_id"]
asset_id = auth.create_user_asset(admin_id, "admin_only.png")
assert auth.delete_user_asset(asset_id, user_id) is False
assert auth.get_user_asset(asset_id) is not None
def test_upload_user_asset_route_stores_the_file_and_returns_a_url(client):
resp = client.post(
"/assets/upload",
data={"file": (io.BytesIO(b"fake-image-bytes"), "photo.png")},
content_type="multipart/form-data",
)
assert resp.status_code == 200
body = resp.get_json()
assert body["id"]
assert "/assets/" in body["url"]
dl = client.get(body["url"])
assert dl.status_code == 200
assert dl.data == b"fake-image-bytes"
def test_upload_user_asset_route_requires_a_file(client):
resp = client.post("/assets/upload", data={}, content_type="multipart/form-data")
assert resp.status_code == 400
def test_serve_user_asset_route_403s_for_another_account(client, user_client):
# Un compte "user" fraîchement inscrit (sans projet) est redirigé vers
# l'onboarding pour toute route hors _REACHABLE_WITHOUT_PROJECT (voir
# core/auth_guard.py) — lui assigner un projet ici isole ce test sur
# le SEUL comportement qu'on veut vérifier : l'isolation par
# propriétaire de "Mes assets", pas le parcours d'onboarding.
with user_client.session_transaction() as sess:
other_user_id = sess["user_id"]
auth.set_project_slug(other_user_id, "pytest_dummy_project")
resp = client.post(
"/assets/upload",
data={"file": (io.BytesIO(b"fake-image-bytes"), "photo.png")},
content_type="multipart/form-data",
)
url = resp.get_json()["url"]
resp2 = user_client.get(url)
assert resp2.status_code == 403