Files
anonymisation/tests/unit/test_gui_v6_app_shell.py
Domi31tls 764cf00581 refactor(gui): intégrer les Règles dans Administration > Profils
Retour Dom : « les règles du profil doivent être dans le menu profil, pas à
part ! ». Même logique que le Masquage — les règles qui influencent
l'anonymisation appartiennent au profil ; un sous-onglet séparé crée la
même confusion.

- Retrait du sous-onglet « Administration > Règles » (_SUBTABS, builder,
  méthode _build_regles supprimée). Sous-onglets restants : Réglages /
  Profils / Partage.
- Section « Profils > Règles du profil » enrichie : wording clair (règles
  d'anonymisation portées par le profil), aperçu illustratif de la table
  des règles (réutilise _rule_row + _HELP_REGLES), édition fine annoncée
  « à venir ».
- Abandon du « Testeur de règle » (écran outil global) pour ne pas
  réintroduire un second réglage métier.

Cible UX : Réglages / Profils (Général・Masquage・Mots・Moteurs・Règles du
profil) / Partage. Test obsolète test_rules_subtab_has_no_unexplained_2
remplacé par test_no_separate_rules_subtab.

262 tests unit OK (0 régression), self-test OK, nav 3 sous-onglets + section
Règles dans Profils + thème OK. Préserve d8bc0cd + GO Qwen. Aucun build/push
sans GO Dom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 12:00:10 +02:00

131 lines
4.0 KiB
Python

"""Shell GUI V6 : robustesse du changement de thème, libellés d'onglets, aide.
Smokes headless (Xvfb) — skip propre si pas de display.
"""
from __future__ import annotations
import pytest
@pytest.fixture
def app():
pytest.importorskip("customtkinter")
try:
from gui_v6.app import AnonymisationApp
a = AnonymisationApp()
except Exception as exc: # pas de display
pytest.skip(f"display Tk indisponible: {exc}")
a.withdraw()
try:
yield a
finally:
try:
a.destroy()
except Exception:
pass
def test_usage_tab_survives_theme_change(app):
"""Retour Dom #1 : l'onglet Utilisation ne doit pas se vider au changement
de thème (le cache d'onglets ne doit pas conserver de widgets détruits)."""
app._show("use")
app.update_idletasks()
assert app._active == "use"
other = "clair" if app._theme_name != "clair" else "sombre"
app.set_theme(other)
app.update_idletasks()
assert app._active == "use"
assert "use" in app._tab_frames
frame = app._tab_frames["use"]
assert frame.winfo_exists() # onglet recréé et vivant, pas un widget mort
def test_main_tab_renamed_to_administration():
"""Retour Dom #2 : l'onglet principal Configuration devient Administration."""
from gui_v6.app import _TABS
labels = [label for _, label in _TABS]
assert any("Administration" in lbl for lbl in labels)
assert not any("Configuration" in lbl for lbl in labels)
def test_no_separate_rules_subtab():
"""Retour Dom : les règles appartiennent au profil → plus de sous-onglet
« Règles » séparé (et donc plus de « Règles 2 » incompréhensible)."""
from gui_v6.tabs.tab_config import _SUBTABS
keys = [key for key, _ in _SUBTABS]
labels = [label for _, label in _SUBTABS]
assert "rul" not in keys
assert not any("Règles" in lbl for lbl in labels)
def test_help_button_opens_help_window(app):
"""Retours Dom #4/#5 : affordance d'aide « ? » réutilisable qui ouvre une
fenêtre d'aide en français."""
from gui_v6 import theme as theme_mod
from gui_v6 import ui_kit
p = theme_mod.get_palette(theme_mod.DEFAULT_THEME)
btn = ui_kit.help_button(app, p, "Cette section reste 100 % locale.", title="Aide test")
assert btn.cget("text") == "?"
win = btn.open_help()
app.update_idletasks()
assert win.winfo_exists()
win.destroy()
def _all_texts(widget) -> list:
out = []
try:
out.append(str(widget.cget("text")))
except Exception:
pass
for child in widget.winfo_children():
out += _all_texts(child)
return out
def test_beta_label_in_product_identity(app):
"""Addendum Dom : indiquer « bêta » à côté du nom produit (en-tête + titre)."""
app.update_idletasks()
assert "bêta" in app.title().lower() or "beta" in app.title().lower()
texts = [t.lower() for t in _all_texts(app)]
assert any("aivanonym" in t for t in texts)
assert any("bêta" in t or "beta" in t for t in texts)
def _count_help_buttons(widget) -> int:
from gui_v6.ui_kit import HelpButton
total = 1 if isinstance(widget, HelpButton) else 0
for child in widget.winfo_children():
total += _count_help_buttons(child)
return total
def test_each_tab_exposes_help(app):
"""Retour Dom #5 : une affordance d'aide « ? » est présente sur chaque onglet."""
for key in ("use", "cfg", "about"):
app._show(key)
app.update_idletasks()
assert _count_help_buttons(app._tab_frames[key]) >= 1, key
def test_navigation_and_theme_change_keep_tabs_alive(app):
"""Navigation + changement de thème : aucun onglet vide/mort."""
for key in ("use", "cfg", "about"):
app._show(key)
app.update_idletasks()
assert app._tab_frames[key].winfo_exists()
app.set_theme("medical")
app.update_idletasks()
for key in ("use", "cfg", "about"):
app._show(key)
app.update_idletasks()
assert app._tab_frames[key].winfo_exists()