Code/tests/integration/conftest.py
Stéphan Peccini cf91d0b69e
test(integration): 3 scénarios E2E Playwright (Fiches, Analyse, Plan d'action)
- Infrastructure test : StreamlitApp helper, réinitialisation session, serveur dédié port 8502
- Scénario Fiches : sélection dossier Assemblage + fiche casques VR
- Scénario Analyse : Serveur→Pays géo, Germanium, Chine, filtre IHH Pays, vérification Sankey
- Scénario Plan d'action : Serveur + Germanium, vérification dashboard criticités

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 11:52:40 +01:00

131 lines
4.3 KiB
Python

"""Fixtures pour les tests d'intégration Playwright + Streamlit."""
import json
import re
import subprocess
import sys
import time
from pathlib import Path
from urllib.request import urlopen
import pytest
pytest.importorskip("playwright")
TEST_PORT = 8502
PROJECT_ROOT = Path(__file__).parent.parent.parent
SESSION_DIR = PROJECT_ROOT / "tmp" / "sessions" / "anonymous"
STATUT_FILE = SESSION_DIR / "statut_general.json"
# État vierge pour garantir des tests reproductibles
ETAT_VIERGE = {
"navigation_onglet": "Instructions",
"theme_mode": "Clair",
"pages": {},
}
class StreamlitApp:
"""Encapsule les interactions avec les widgets Streamlit via Playwright."""
RERUN_WAIT = 2000 # ms à attendre après chaque interaction widget
def __init__(self, page):
"""Initialise avec une page Playwright."""
self.page = page
def naviguer_vers(self, onglet):
"""Clique sur un onglet du menu latéral."""
self.page.get_by_role("button", name=onglet).click()
self.page.wait_for_timeout(self.RERUN_WAIT)
def choisir_selectbox(self, label, valeur):
"""Sélectionne une valeur dans un selectbox Streamlit."""
combobox = self.page.get_by_role("combobox", name=re.compile(label))
combobox.click()
self.page.get_by_role("option", name=valeur).click()
self.page.wait_for_timeout(self.RERUN_WAIT)
def ajouter_multiselect(self, label, valeur):
"""Ajoute une valeur à un multiselect Streamlit en filtrant par texte."""
combobox = self.page.get_by_role("combobox", name=re.compile(label))
combobox.click()
self.page.wait_for_timeout(500)
self.page.keyboard.type(valeur, delay=50)
self.page.wait_for_timeout(1000)
self.page.get_by_role("option", name=valeur).click()
# Fermer le dropdown pour éviter qu'il n'intercepte les clics suivants
self.page.keyboard.press("Escape")
self.page.wait_for_timeout(self.RERUN_WAIT)
def cocher(self, label):
"""Coche une checkbox Streamlit via le label texte (l'input natif est caché)."""
texte = self.page.get_by_text(re.compile(label)).first
texte.scroll_into_view_if_needed()
texte.click()
self.page.wait_for_timeout(self.RERUN_WAIT)
def choisir_radio(self, valeur):
"""Sélectionne une option radio Streamlit via le label texte (l'input natif est caché)."""
# Cibler le <p> dans le conteneur du radiogroup
radio_label = self.page.locator(f'[role="radiogroup"] p:text-is("{valeur}")')
radio_label.scroll_into_view_if_needed()
radio_label.click()
self.page.wait_for_timeout(self.RERUN_WAIT)
def cliquer_bouton(self, label):
"""Clique sur un bouton Streamlit."""
self.page.get_by_role("button", name=re.compile(label)).click()
self.page.wait_for_timeout(self.RERUN_WAIT)
def _reinitialiser_session():
"""Remet le fichier de session à un état vierge."""
SESSION_DIR.mkdir(parents=True, exist_ok=True)
STATUT_FILE.write_text(json.dumps(ETAT_VIERGE, ensure_ascii=False, indent=2))
@pytest.fixture(scope="session")
def streamlit_server():
"""Démarre un serveur Streamlit dédié aux tests d'intégration."""
_reinitialiser_session()
url = f"http://localhost:{TEST_PORT}"
process = subprocess.Popen(
[
sys.executable, "-m", "streamlit", "run", "fabnum.py",
"--server.port", str(TEST_PORT),
"--server.headless", "true",
"--browser.gatherUsageStats", "false",
],
cwd=str(PROJECT_ROOT),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
for _ in range(30):
try:
response = urlopen(url)
if response.status == 200:
break
except OSError:
pass
time.sleep(1)
else:
process.terminate()
pytest.fail("Le serveur Streamlit n'a pas démarré en 30 secondes")
yield url
process.terminate()
process.wait(timeout=10)
@pytest.fixture
def app(page, streamlit_server):
"""Application Streamlit prête à interagir (état réinitialisé)."""
_reinitialiser_session()
page.set_viewport_size({"width": 1280, "height": 900})
page.goto(streamlit_server)
page.wait_for_timeout(3000)
return StreamlitApp(page)