Fix Jauge always reading the object's most recent row
A Jauge could only target a whole object, not a specific record — three gauges pointing at the same "value" field (e.g. Réputation/ Trésorerie/Confiance in one "jauge" object) all silently showed the most recent row's value, with no way to tell them apart. Add "Enregistrement (ligne) à suivre" (row_id) so a Jauge targets one specific row, and "Champ contenant le nom" (champ_nom) to show a label above the bar — both as dropdowns populated from the object's actual fields/rows (previously "Champ numérique à afficher" was free text the user had to type correctly by hand). No regression: without row_id the widget still falls back to the latest row, exactly as before. Extract data_definition_options() (rows+fields for a definition) out of routes/screens/screen_edit.py so controls_with_values.py can reuse it server-side for the initial render; a small client-side handler (bindJaugeDefinitionSelect) repopulates the same selects live when the tracked object is changed without leaving the panel. Verified live with Playwright: picking "jauge" then "Confiance" then "value"/"name" in the panel renders an 80%-filled, green-leaning bar labelled "Confiance" on /play — not the 20%/50% of the other rows.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
"""Tests du widget Jauge (2.1 : binding live d'une donnée vers un style)."""
|
||||
import re
|
||||
|
||||
import db
|
||||
|
||||
|
||||
def _create_screen(client, slug, name="Accueil"):
|
||||
resp = client.post(f"/game/{slug}/screens/new", data={"name": name}, follow_redirects=False)
|
||||
@@ -83,6 +85,86 @@ def test_gauge_value_clamped_visually_when_out_of_range(client, game):
|
||||
assert "width:100.0%" in html
|
||||
|
||||
|
||||
# ---------- Choix de l'enregistrement (plusieurs jauges dans un même objet)
|
||||
# et champ affiché comme nom au-dessus de la barre ----------
|
||||
|
||||
def _create_jauge_object_with_rows(client, slug):
|
||||
"""Un seul objet "jauge" avec trois enregistrements (name/value), comme
|
||||
dans le scénario remonté : Réputation/Trésorerie/Confiance, toutes à 50
|
||||
— le bug était de ne pas pouvoir distinguer laquelle une Jauge suit."""
|
||||
resp = client.post(f"/game/{slug}/objects/new", data={
|
||||
"object_name": "jauge",
|
||||
"field_name[]": ["name", "value"], "field_type[]": ["texte", "nombre_entier"],
|
||||
"field_relation[]": ["", ""], "field_required[]": ["0", "0"],
|
||||
}, follow_redirects=False)
|
||||
def_id = int(resp.headers["Location"].rstrip("/").split("/")[-1])
|
||||
for name, value in [("Réputation", "50"), ("Trésorerie", "20"), ("Confiance", "80")]:
|
||||
client.post(f"/game/{slug}/objects/{def_id}/data/new", data={"name": name, "value": value}, follow_redirects=False)
|
||||
# La route de création redirige vers la liste (pas d'id de ligne dans le
|
||||
# Location) — on relit les lignes enregistrées pour retrouver leurs id.
|
||||
definition = db.get_definition(slug, def_id)
|
||||
row_ids = {r["name"]: r["id"] for r in db.list_rows(slug, definition)}
|
||||
return def_id, row_ids
|
||||
|
||||
|
||||
def test_gauge_row_id_distinguishes_between_records_of_the_same_object(client, game):
|
||||
"""Le bug remonté : trois Jauges reliées au même objet (via "value")
|
||||
affichaient toutes la même valeur (celle de la ligne la plus récente),
|
||||
faute de pouvoir choisir LAQUELLE suivre. row_id doit permettre de
|
||||
cibler "Confiance" (80%) plutôt que "Trésorerie" (20%)."""
|
||||
def_id, row_ids = _create_jauge_object_with_rows(client, game)
|
||||
screen_id = _create_screen(client, game)
|
||||
resp = client.post(f"/game/{game}/screens/{screen_id}/elements/add", data={"widget": "jauge"}, follow_redirects=False)
|
||||
jauge_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
|
||||
client.post(f"/game/{game}/elements/{jauge_id}/save", data={
|
||||
"ctrl_definition_id": str(def_id), "ctrl_row_id": str(row_ids["Confiance"]),
|
||||
"ctrl_champ": "value", "ctrl_min": "0", "ctrl_max": "100",
|
||||
})
|
||||
html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode()
|
||||
assert "width:80.0%" in html
|
||||
|
||||
|
||||
def test_gauge_without_row_id_falls_back_to_latest_row_no_regression(client, game):
|
||||
"""Sans row_id réglé (jauges créées avant ce champ, ou objet à une seule
|
||||
ligne comme dans test_jauge.py historique) : comportement inchangé, la
|
||||
ligne la plus récente."""
|
||||
def_id, _row_ids = _create_jauge_object_with_rows(client, game)
|
||||
screen_id = _create_screen(client, game)
|
||||
resp = client.post(f"/game/{game}/screens/{screen_id}/elements/add", data={"widget": "jauge"}, follow_redirects=False)
|
||||
jauge_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
|
||||
client.post(f"/game/{game}/elements/{jauge_id}/save", data={
|
||||
"ctrl_definition_id": str(def_id), "ctrl_champ": "value", "ctrl_min": "0", "ctrl_max": "100",
|
||||
})
|
||||
html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode()
|
||||
assert "width:80.0%" in html # "Confiance", ajoutée en dernier
|
||||
|
||||
|
||||
def test_gauge_name_field_renders_above_the_bar(client, game):
|
||||
def_id, row_ids = _create_jauge_object_with_rows(client, game)
|
||||
screen_id = _create_screen(client, game)
|
||||
resp = client.post(f"/game/{game}/screens/{screen_id}/elements/add", data={"widget": "jauge"}, follow_redirects=False)
|
||||
jauge_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
|
||||
client.post(f"/game/{game}/elements/{jauge_id}/save", data={
|
||||
"ctrl_definition_id": str(def_id), "ctrl_row_id": str(row_ids["Confiance"]),
|
||||
"ctrl_champ": "value", "ctrl_champ_nom": "name", "ctrl_min": "0", "ctrl_max": "100",
|
||||
})
|
||||
html = client.get(f"/game/{game}/play").data.decode()
|
||||
assert ">Confiance<" in html
|
||||
|
||||
|
||||
def test_gauge_without_champ_nom_shows_no_name_no_regression(client, game):
|
||||
def_id, row_ids = _create_jauge_object_with_rows(client, game)
|
||||
screen_id = _create_screen(client, game)
|
||||
resp = client.post(f"/game/{game}/screens/{screen_id}/elements/add", data={"widget": "jauge"}, follow_redirects=False)
|
||||
jauge_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
|
||||
client.post(f"/game/{game}/elements/{jauge_id}/save", data={
|
||||
"ctrl_definition_id": str(def_id), "ctrl_row_id": str(row_ids["Confiance"]),
|
||||
"ctrl_champ": "value", "ctrl_min": "0", "ctrl_max": "100",
|
||||
})
|
||||
html = client.get(f"/game/{game}/play").data.decode()
|
||||
assert ">Confiance<" not in html
|
||||
|
||||
|
||||
# ---------- Régression : clics multipliés après un rafraîchissement de
|
||||
# données (bouton +10/-10 relié à une jauge) ----------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user