refactor(pricing): 3 Cloud en rangée + DictIA LOCAL bloc dédié 'Vous en êtes propriétaire'

Restructure _pricing_tiers.html : les 3 forfaits Cloud (Basic 189$/Essentiel 349$/Pro 549$ recommandé) sont maintenant en grid responsive 1/2/3 cols, et DictIA LOCAL est sorti de la grille principale pour devenir un bloc large dédié 'propriété' avec :

- badge 'Au Québec · par InnovA AI' (SVG map-pin, sans emoji 🇨🇦)
- H3 'Vous en êtes propriétaire.' avec grad-text
- 5 bullets checkmark (PC+GPU RTX, 100 % local, assemblé QC, installation incluse, achat direct < 34 700 $)
- CTA 'Voir les serveurs disponibles' → /contact?plan=dictia-local
- mockup serveur à droite (SVG rack + 6 specs : Interface web, PC gaming, RTX 5070 Ti 16 Go, WhisperX+Mistral, DictIA pré-installé, Votre propriété)
- pricing tagline visible '5 998 $ An 1 · 500 $/an dès An 2'
- decorative orbs background (b1 + b3) pour distinguer du grid Cloud

Aussi mis à jour /tarifs (H1 'Trois forfaits Cloud + DictIA LOCAL' au lieu de 'Quatre forfaits') et tests pour refléter le nouveau slug /contact?plan=dictia-local (au lieu du /checkout/dictia-local d'avant). Conserve V3 radii (rounded-none/rounded/rounded-full), palette brand (b1/b2/b3/navy), OQLF NBSP, ARIA WCAG, zéro emoji.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Allison
2026-04-28 21:28:46 -04:00
parent 1c4cafaf69
commit e06cba2123
5 changed files with 171 additions and 44 deletions

View File

@@ -360,28 +360,32 @@ def test_pricing_recommended_tier_is_cloud_pro():
def test_pricing_cta_labels_v7():
"""CTAs reflect v7.0 forfait choice (Démarrer en Cloud / Choisir Essentiel / Commander Pro / Configurer DictIA Local)."""
"""CTAs reflect v7.0 forfait choice — 3 Cloud go to /checkout, DictIA LOCAL goes to /contact?plan=dictia-local."""
client = app.test_client()
body = client.get('/').data.decode('utf-8')
for slug in ['cloud-basic', 'cloud-essentiel', 'cloud-pro', 'dictia-local']:
# 3 Cloud forfaits use /checkout/<slug>
for slug in ['cloud-basic', 'cloud-essentiel', 'cloud-pro']:
assert f'href="/checkout/{slug}"' in body, f"Missing checkout link for {slug}"
# CTA labels match the macro callers in _pricing_tiers.html
assert 'Démarrer en Cloud' in body or 'D&eacute;marrer en Cloud' in body
assert 'Choisir Essentiel' in body
assert 'Commander Pro' in body
assert 'Configurer DictIA Local' in body
# DictIA LOCAL now has a dedicated block with a contact CTA (no /checkout slug)
assert 'Voir les serveurs disponibles' in body, "Missing DictIA LOCAL block CTA label"
assert '/contact?plan=dictia-local' in body, "Missing DictIA LOCAL contact CTA href"
def test_pricing_features_use_safe_filter_no_double_escape():
"""Pricing card features piped through | safe — '&nbsp;' must render single-escaped, not double."""
client = app.test_client()
body = client.get('/').data.decode('utf-8')
# Capacity chips use NBSP
# Capacity chips use NBSP (3 Cloud forfaits)
assert '~165&nbsp;h audio/mois' in body, "Missing Cloud BASIC capacity chip"
assert '100&nbsp;Go' in body, "Missing Cloud BASIC storage chip"
assert '~660&nbsp;h audio/mois' in body, "Missing Cloud PRO capacity chip"
assert '500&nbsp;Go' in body, "Missing Cloud PRO storage chip"
assert '2&nbsp;To SSD' in body, "Missing DictIA LOCAL storage chip"
# DictIA LOCAL dedicated block — server visual mockup uses NBSP for GPU spec
assert 'RTX 5070&nbsp;Ti 16&nbsp;Go' in body, "Missing DictIA LOCAL GPU spec line in dedicated block"
# WhisperX precision claim w/ NBSP
assert 'WhisperX Large-v3' in body, "Missing WhisperX Large-v3 mention"
# Loi 25 with NBSP
@@ -462,8 +466,9 @@ def test_pricing_cta_url_no_double_slash():
"""pricing_card uses cta_url.rstrip('/') so href never has '//' (regression guard)."""
client = app.test_client()
body = client.get('/').data.decode('utf-8')
# All 4 CTAs use the default cta_url='/checkout' (no trailing slash) — so /checkout/<slug>
for slug in ['cloud-basic', 'cloud-essentiel', 'cloud-pro', 'dictia-local']:
# The 3 Cloud forfaits use the default cta_url='/checkout' (no trailing slash) — so /checkout/<slug>
# DictIA LOCAL is presented in a dedicated block with /contact?plan=dictia-local (not via pricing_card macro)
for slug in ['cloud-basic', 'cloud-essentiel', 'cloud-pro']:
assert f'href="/checkout/{slug}"' in body, f"Missing single-slash href for {slug}"
assert f'href="/checkout//{slug}"' not in body, f"Double-slash regression for {slug}"

View File

@@ -34,7 +34,7 @@ def test_tarifs_has_h1_with_anchor():
def test_tarifs_renders_4_pricing_cards_v7():
"""Tarifs page renders the v7.0 4 forfaits + Pro+ chip."""
"""Tarifs page renders the v7.0 3 Cloud forfaits + DictIA LOCAL dedicated block + Pro+ chip."""
client = app.test_client()
body = client.get('/tarifs').data.decode('utf-8')
for tier in ['Cloud BASIC', 'Cloud ESSENTIEL', 'Cloud PRO', 'DictIA LOCAL']:
@@ -45,11 +45,15 @@ def test_tarifs_renders_4_pricing_cards_v7():
assert '549&nbsp;$' in body
assert '485&nbsp;$' in body # Cloud Pro onboarding
assert '5&nbsp;998&nbsp;$' in body # DictIA Local An 1
# Checkout slugs
# 3 Cloud forfaits use checkout slugs
assert 'href="/checkout/cloud-basic"' in body
assert 'href="/checkout/cloud-essentiel"' in body
assert 'href="/checkout/cloud-pro"' in body
assert 'href="/checkout/dictia-local"' in body
# DictIA LOCAL has its own dedicated block with a contact CTA (no /checkout slug)
assert '/contact?plan=dictia-local' in body, "Missing DictIA LOCAL block contact CTA"
assert 'Vous en êtes' in body or 'Vous en &ecirc;tes' in body, \
"Missing DictIA LOCAL block headline 'Vous en êtes propriétaire'"
assert 'Serveur DictIA' in body, "Missing DictIA LOCAL block server visual mockup label"
# Pro+ chip with /contact link
assert 'Pro+' in body
assert '/contact?pro-plus=1' in body