"""FlowDeck — onglets compressibles du sidebar (Home / Chat / Meeting / Inbox). La barre latérale gauche devient un sélecteur d'onglet : le bouton actif s'étend en pilule avec son libellé, les autres se réduisent à leur icône, et chaque sélection remplace intégralement le contenu de la barre latérale. * ordre exact des onglets : Home → Chat → Meeting → Inbox ; * quatre panneaux Alpine dédiés (``sidebarTab === …``) ; * contenu branché sur des données réelles : historique des conversations agent (``/api/agent/conversations``), événements à venir (``GET /api/v2/meetings/upcoming``, nouveau) et notifications (``/api/notifications``). """ from __future__ import annotations import json import re from datetime import UTC, datetime, timedelta from pathlib import Path import pytest from conftest import login_test_client TPL = Path("app/templates/base.html") CSS = Path("static/css/app.css") @pytest.fixture def client(): """Same isolated temp DB contract as tests/conftest.py::client.""" import os import tempfile db_file = tempfile.NamedTemporaryFile(suffix=".db", delete=False) db_path = db_file.name db_file.close() backup_dir = tempfile.mkdtemp(prefix="fd_backups_") data_dir = tempfile.mkdtemp(prefix="fd_data_") os.environ["DATABASE_URL"] = f"sqlite:///{db_path}" os.environ["APP_SECRET_KEY"] = "test-secret-for-tests" os.environ["RATE_LIMIT_ENABLED"] = "false" os.environ["LLM_PROVIDER"] = "offline" os.environ["FLOWDECK_DATA_DIR"] = data_dir import app.config s = app.config.settings s.database_url = f"sqlite:///{db_path}" s.app_secret_key = "test-secret-for-tests" s.rate_limit_enabled = False s.backup_enabled = False s.backup_dir = backup_dir s.project_sync_enabled = False from app.db import init_db from app.main import app init_db() from fastapi.testclient import TestClient c = login_test_client(TestClient(app)) try: yield c finally: try: os.unlink(db_path) except FileNotFoundError: pass def _render(client) -> str: r = client.post("/api/local-workspace/items", json={"name": "TabsProbe"}) assert r.status_code == 200, r.text page = client.get(f"/pages/{r.json()['id']}") assert page.status_code == 200 return page.text # ══════════════════ ordre et libellés des onglets ══════════════════ def test_tab_order_is_home_chat_meeting_inbox(client): tpl = TPL.read_text(encoding="utf-8") row = re.search(r'