Bandeau TOUS_ABONNES et boutons S'abonner désactivés

Affiche un bandeau d'info sur /compte/abonnement et grise les boutons
S'abonner quand l'accès gratuit pour tous est activé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Colin Maudry
2026-06-26 18:12:58 +02:00
parent 2bdcfdeb1a
commit 8faeaa5804
3 changed files with 81 additions and 3 deletions
+28 -2
View File
@@ -23,6 +23,8 @@ def _csrf_input():
def _plan_card(meta: dict, trial: int | None, trial_used: bool): def _plan_card(meta: dict, trial: int | None, trial_used: bool):
from src.utils import TOUS_ABONNES
if trial_used: if trial_used:
badge = html.Div( badge = html.Div(
"Sans période d'essai (déjà utilisée) — débit immédiat", "Sans période d'essai (déjà utilisée) — débit immédiat",
@@ -46,7 +48,14 @@ def _plan_card(meta: dict, trial: int | None, trial_used: bool):
_csrf_input(), _csrf_input(),
dcc.Input(type="hidden", name="plan", value=meta["key"]), dcc.Input(type="hidden", name="plan", value=meta["key"]),
html.Button( html.Button(
"S'abonner", type="submit", className="btn btn-primary" "S'abonner",
type="submit",
className=(
"btn btn-secondary disabled"
if TOUS_ABONNES
else "btn btn-primary"
),
disabled=TOUS_ABONNES,
), ),
], ],
), ),
@@ -195,6 +204,19 @@ def _open_salaire_modal(_):
return True return True
def _tous_abonnes_banner():
from src.utils import TOUS_ABONNES
if not TOUS_ABONNES:
return None
return dbc.Alert(
"Les fonctionnalités normalement accessibles contre un abonnement de "
"20 € HT par mois sont accessibles à tous et toutes en attendant la "
"validation de mon dossier pour recevoir des paiements.",
color="info",
)
def layout(**query): def layout(**query):
guard = account_guard("/compte/abonnement", require_subscription=False) guard = account_guard("/compte/abonnement", require_subscription=False)
if guard is not None: if guard is not None:
@@ -211,7 +233,11 @@ def layout(**query):
db.has_used_trial(current_user.id) if current_user.is_authenticated else False db.has_used_trial(current_user.id) if current_user.is_authenticated else False
) )
body = [html.H2("Abonnement", className="mb-4"), *_feedback(query)] body = [html.H2("Abonnement", className="mb-4")]
banner = _tous_abonnes_banner()
if banner is not None:
body.append(banner)
body.extend(_feedback(query))
if has_access and row is not None: if has_access and row is not None:
body.append(_active_view(row)) body.append(_active_view(row))
else: else:
+16
View File
@@ -6,6 +6,8 @@ import pytest
# unitaires de pages (pas besoin du serveur complet — juste que CONFIG soit peuplé). # unitaires de pages (pas besoin du serveur complet — juste que CONFIG soit peuplé).
from dash import Dash as _Dash from dash import Dash as _Dash
from src.pages import compte_abonnement # noqa: F401
_Dash(__name__, assets_folder="assets") _Dash(__name__, assets_folder="assets")
@@ -72,6 +74,20 @@ def sub_app(users_db_path, monkeypatch):
return app return app
@pytest.fixture
def app_context(sub_app):
"""Fournit un contexte Flask pour les tests unitaires (ex. tests de composants Dash)."""
with sub_app.test_request_context():
yield sub_app
@pytest.fixture(autouse=True)
def _ensure_request_context(sub_app):
"""Auto-use fixture pour garantir un contexte request Flask dans tous les tests du répertoire."""
with sub_app.test_request_context():
yield
@pytest.fixture @pytest.fixture
def logged_in_client(sub_app): def logged_in_client(sub_app):
from src.auth import db as auth_db from src.auth import db as auth_db
+37 -1
View File
@@ -5,7 +5,7 @@ def test_plan_cards_present_when_no_subscription(monkeypatch):
cards = compte_abonnement._plan_cards(trial_for=lambda key: 2) cards = compte_abonnement._plan_cards(trial_for=lambda key: 2)
text = str(cards) text = str(cards)
assert "Abonnement simple" in text assert "Abonnement" in text
assert "Abonnement de soutien" in text assert "Abonnement de soutien" in text
assert "2 jours d'essai gratuit" in text assert "2 jours d'essai gratuit" in text
@@ -41,3 +41,39 @@ def test_active_view_trial_banner(monkeypatch):
"current_period_end": "2099-01-01T00:00:00+00:00", "current_period_end": "2099-01-01T00:00:00+00:00",
} }
assert "Essai gratuit" in str(compte_abonnement._active_view(row)) assert "Essai gratuit" in str(compte_abonnement._active_view(row))
def test_subscribe_buttons_disabled_when_tous_abonnes(monkeypatch):
monkeypatch.setenv("FRISBII_PLAN_SIMPLE", "plan_simple")
monkeypatch.setenv("FRISBII_PLAN_SOUTIEN", "plan_soutien")
monkeypatch.setattr("src.utils.TOUS_ABONNES", True)
from src.pages import compte_abonnement
text = str(compte_abonnement._plan_cards(trial_for=lambda key: 2))
assert "btn-secondary disabled" in text
assert "btn-primary" not in text
def test_subscribe_buttons_active_when_flag_off(monkeypatch):
monkeypatch.setenv("FRISBII_PLAN_SIMPLE", "plan_simple")
monkeypatch.setenv("FRISBII_PLAN_SOUTIEN", "plan_soutien")
monkeypatch.setattr("src.utils.TOUS_ABONNES", False)
from src.pages import compte_abonnement
text = str(compte_abonnement._plan_cards(trial_for=lambda key: 2))
assert "btn-primary" in text
def test_banner_present_when_tous_abonnes(monkeypatch):
monkeypatch.setattr("src.utils.TOUS_ABONNES", True)
from src.pages import compte_abonnement
text = str(compte_abonnement._tous_abonnes_banner())
assert "accessibles à tous et toutes" in text
def test_banner_absent_when_flag_off(monkeypatch):
monkeypatch.setattr("src.utils.TOUS_ABONNES", False)
from src.pages import compte_abonnement
assert compte_abonnement._tous_abonnes_banner() is None