"""Tests de la route publique /jouer/ (routes/public_play/) — état par joueur, Phase 1. Contrairement aux autres tests, ceux-ci utilisent DIRECTEMENT flask_app.test_client() (pas la fixture `client`) pour de vrais visiteurs anonymes, jamais connectés — le but est justement de vérifier que core/auth_guard.py laisse passer ces routes sans session.""" import json import re import db from conftest import flask_app def _create_screen(client, slug, name="Accueil"): resp = client.post(f"/game/{slug}/screens/new", data={"name": name}, follow_redirects=False) return int(re.search(r"/screens/(\d+)/edit", resp.headers["Location"]).group(1)) def _add_flow_node(client, slug, screen_id, **fields): resp = client.post( f"/game/{slug}/screens/{screen_id}/flow/nodes/add", data=json.dumps(fields), content_type="application/json", ) assert resp.status_code == 200 return resp.get_json()["id"] def test_public_route_404_until_explicitly_published(client, game): anon = flask_app.test_client() resp = anon.get(f"/jouer/{game}") assert resp.status_code == 404 client.post(f"/game/{game}/toggle-public-played", data={"value": "1"}) resp = anon.get(f"/jouer/{game}") assert resp.status_code == 200 client.post(f"/game/{game}/toggle-public-played", data={"value": "0"}) resp = anon.get(f"/jouer/{game}") assert resp.status_code == 404 def test_public_route_works_without_any_login_session(client, game): """La garde globale (core/auth_guard.py) ne doit PAS exiger de session pour cette route — c'est tout le sens de "publique".""" client.post(f"/game/{game}/toggle-public-played", data={"value": "1"}) anon = flask_app.test_client() with anon.session_transaction() as sess: assert "user_id" not in sess resp = anon.get(f"/jouer/{game}") assert resp.status_code == 200 assert b"CSRF_TOKEN" in resp.data or b"gameData" in resp.data def test_public_route_sets_player_id_cookie(client, game): client.post(f"/game/{game}/toggle-public-played", data={"value": "1"}) anon = flask_app.test_client() resp = anon.get(f"/jouer/{game}") assert "forge_player_id" in resp.headers.get("Set-Cookie", "") def test_two_anonymous_players_get_independent_variable_state(client, game): """Bout en bout, via HTTP : deux visiteurs anonymes (deux clients de test SÉPARÉS, donc deux cookies forge_player_id différents) sur le même jeu publié -> chacun sa propre valeur pour une variable per_player, modifiée via l'action "Modifier une variable" (le vrai chemin d'exécution du mode jouable, routes/public_play/ flow_node_run_variable_public.py).""" db.create_global_variable(game, "score", "nombre_entier", "0", per_player=True) screen_id = _create_screen(client, game) node_id = _add_flow_node( client, game, screen_id, node_type="action", action_type="modifier_variable", target_variable="score", data_operation="incrementer", data_value="10", ) client.post(f"/game/{game}/toggle-public-played", data={"value": "1"}) alice = flask_app.test_client() alice.get(f"/jouer/{game}") # pose le cookie resp = alice.post(f"/jouer/{game}/flow/nodes/{node_id}/run-variable") assert resp.get_json()["ok"] is True bob = flask_app.test_client() bob.get(f"/jouer/{game}") resp = bob.post(f"/jouer/{game}/flow/nodes/{node_id}/run-variable") resp = bob.post(f"/jouer/{game}/flow/nodes/{node_id}/run-variable") assert resp.get_json()["ok"] is True assert db.get_global_variable(game, "score", player_id="__shared__")["value"] == "0" alice_payload = alice.get(f"/jouer/{game}/runtime-payload").get_json() bob_payload = bob.get(f"/jouer/{game}/runtime-payload").get_json() assert alice_payload["variables"]["score"]["value"] == "10" assert bob_payload["variables"]["score"]["value"] == "20" def test_creator_preview_unaffected_by_public_players(client, game): """L'aperçu créateur (/game//play, connecté) doit continuer de voir/modifier PLAYER_SHARED, jamais l'état d'un joueur public.""" db.create_global_variable(game, "score", "nombre_entier", "0", per_player=True) screen_id = _create_screen(client, game) node_id = _add_flow_node( client, game, screen_id, node_type="action", action_type="modifier_variable", target_variable="score", data_operation="incrementer", data_value="10", ) client.post(f"/game/{game}/toggle-public-played", data={"value": "1"}) alice = flask_app.test_client() alice.get(f"/jouer/{game}") alice.post(f"/jouer/{game}/flow/nodes/{node_id}/run-variable") resp = client.get(f"/game/{game}/play") assert resp.status_code == 200 creator_payload = client.get(f"/game/{game}/runtime-payload").get_json() assert creator_payload["variables"]["score"]["value"] == "0"