Dev #1

Merged
w-vandal merged 62 commits from dev into main 2026-08-26 04:56:44 +00:00
2 changed files with 71 additions and 0 deletions
Showing only changes of commit 4dc42a7f3b - Show all commits
+30
View File
@@ -30,6 +30,36 @@ def list_elements(slug, screen_id, enforce_visibility=False):
d["style"] = json.loads(d["style"] or "{}")
d["attributes"] = json.loads(d["attributes"] or "{}")
result.append(d)
# Descendant d'un exemplaire d'élément de jeu (element_type_id réglé sur
# un ancêtre) : un ancien enfant copié en base par l'ex-instantiate_
# template_tree (mécanisme retiré, voir add_element.py) — son contenu
# vient désormais TOUJOURS en direct de l'écran-modèle au moment du
# rendu (voir render_element_html.py/_render_element_type_children),
# jamais de ces lignes, qui peuvent encore traîner en base pour un
# exemplaire posé avant ce changement. Exclu ici pour ne plus jamais
# apparaître sélectionnable dans l'arborescence de l'éditeur — sinon
# ses réglages, plus jamais synchronisés avec le modèle, donnaient
# l'impression trompeuse que "les propriétés ne sont pas prises en
# compte" (une taille de texte modifiée dans le modèle ne se reflétant
# jamais sur cette ligne fantôme, toujours sélectionnable à l'écran).
by_id = {d["id"]: d for d in result}
def _has_linked_ancestor(d):
seen = set()
parent_id = d.get("parent_id")
while parent_id and parent_id not in seen:
seen.add(parent_id)
parent = by_id.get(parent_id)
if not parent:
return False
if parent.get("element_type_id"):
return True
parent_id = parent.get("parent_id")
return False
result = [d for d in result if not _has_linked_ancestor(d)]
children_map = {}
for d in result:
if d.get("parent_id"):
+41
View File
@@ -56,6 +56,47 @@ def test_editing_the_template_updates_the_play_page_too(client, game):
assert "Contenu mis à jour" in html
def test_leftover_orphaned_children_no_longer_appear_in_the_editor(client, game):
"""Régression : un exemplaire posé AVANT ce mécanisme (ou tout ancien
enfant copié en base par l'ex-instantiate_template_tree, retiré)
laisse d'éventuelles lignes orphelines en base sous l'exemplaire — leur
contenu n'est plus jamais rendu (voir render_element_html.py), mais
elles restaient sélectionnables dans l'arborescence de l'éditeur, avec
leurs propres réglages jamais synchronisés avec le modèle : une taille
de texte modifiée dans le modèle ne s'y reflétait jamais, donnant
l'impression trompeuse que "les propriétés ne sont pas prises en
compte"."""
import json
import db
et, _titre_id = _create_card_element_type(client, game)
screen_id = _create_screen(client, game)
resp = client.post(
f"/game/{game}/screens/{screen_id}/elements/add",
data={"widget": "__catalogue__", "element_type_id": str(et["id"])},
follow_redirects=False,
)
instance_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
conn = db.connect(game)
conn.execute(
"""INSERT INTO _screen_elements (screen_id, parent_id, widget, content, attributes, x, y, width, height, z_index, style)
VALUES (?, ?, 'titre', 'Ancien contenu figé', '{}', 10, 10, 50, 20, 1, ?)""",
(screen_id, instance_id, json.dumps({"font-size": "21px"})),
)
orphan_id = conn.execute("SELECT last_insert_rowid() AS id").fetchone()["id"]
conn.commit()
conn.close()
html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode()
assert f'id="elt-{orphan_id}"' not in html
assert "Ancien contenu figé" not in html
html_selected = client.get(f"/game/{game}/screens/{screen_id}/edit?selected={orphan_id}").data.decode()
assert 'value="21' not in html_selected
def test_instance_position_on_screen_is_independent_per_instance(client, game):
"""Non-régression : la position/taille sur l'écran reste propre à
chaque exemplaire (seul le CONTENU intérieur est désormais partagé)."""