"""Tests de la timeline d'animation : clips Animate.css ou personnalisés (images-clés), posés sur la piste d'un élément, avec un instant de départ et une durée sur l'axe du temps (secondes depuis l'affichage de l'écran).""" import json import re from conftest import play_js_bundle 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_element(client, slug, screen_id, widget): resp = client.post(f"/game/{slug}/screens/{screen_id}/elements/add", data={"widget": widget}, follow_redirects=False) return int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1)) def test_animate_css_clip_persists(client, game): screen_id = _create_screen(client, game) el_id = _add_element(client, game, screen_id, "titre") resp = client.post( f"/game/{game}/screens/{screen_id}/animations/clips/add", data=json.dumps({ "element_id": el_id, "kind": "animate_css", "animate_name": "bounce", "start_time": "1.5", "duration": "2", "delay": "0", "easing": "ease", "iteration_count": "1", }), content_type="application/json", ) assert resp.status_code == 200 clip = resp.get_json() assert clip["kind"] == "animate_css" assert clip["animate_name"] == "bounce" assert clip["start_time"] == 1.5 assert clip["duration"] == 2.0 assert clip["element_id"] == el_id def test_custom_keyframes_clip_persists(client, game): screen_id = _create_screen(client, game) el_id = _add_element(client, game, screen_id, "conteneur") keyframes = [{"percent": 0, "props": {"opacity": "0"}}, {"percent": 100, "props": {"opacity": "1"}}] resp = client.post( f"/game/{game}/screens/{screen_id}/animations/clips/add", data=json.dumps({ "element_id": el_id, "kind": "custom", "custom_keyframes": keyframes, "start_time": "0", "duration": "3", }), content_type="application/json", ) assert resp.status_code == 200 clip = resp.get_json() assert clip["kind"] == "custom" assert json.loads(clip["custom_keyframes"]) == keyframes def test_clip_update_changes_timing(client, game): screen_id = _create_screen(client, game) el_id = _add_element(client, game, screen_id, "bouton") clip = client.post( f"/game/{game}/screens/{screen_id}/animations/clips/add", data=json.dumps({"element_id": el_id, "kind": "animate_css", "animate_name": "fadeIn"}), content_type="application/json", ).get_json() resp = client.post( f"/game/{game}/animations/clips/{clip['id']}/update", data=json.dumps({"start_time": "4", "duration": "0.5"}), content_type="application/json", ) assert resp.status_code == 200 updated = resp.get_json() assert updated["start_time"] == 4.0 assert updated["duration"] == 0.5 def test_clip_delete_removes_it(client, game): screen_id = _create_screen(client, game) el_id = _add_element(client, game, screen_id, "bouton") clip = client.post( f"/game/{game}/screens/{screen_id}/animations/clips/add", data=json.dumps({"element_id": el_id, "kind": "animate_css", "animate_name": "tada"}), content_type="application/json", ).get_json() resp = client.post(f"/game/{game}/animations/clips/{clip['id']}/delete") assert resp.status_code == 200 html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode() assert f'"id": {clip["id"]}' not in html def test_screen_edit_exposes_timeline_panel_and_animate_css(client, game): screen_id = _create_screen(client, game) html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode() assert "animTabPanel" in html assert "Timeline d'animation" in html assert "animate.min.css" in html def test_play_page_exposes_animation_runtime_and_animate_css(client, game): resp = client.get(f"/game/{game}/play") html = resp.data.decode() assert "animate.min.css" in html js = play_js_bundle() assert "runAnimationTimeline" in js assert "injectCustomKeyframes" in js def test_play_page_payload_includes_clip(client, game): screen_id = _create_screen(client, game) el_id = _add_element(client, game, screen_id, "titre") client.post( f"/game/{game}/screens/{screen_id}/animations/clips/add", data=json.dumps({"element_id": el_id, "kind": "animate_css", "animate_name": "pulse", "start_time": "2"}), content_type="application/json", ) html = client.get(f"/game/{game}/play").data.decode() assert '"animate_name": "pulse"' in html assert '"start_time": 2.0' in html