- Rollback gestion d'équations : écriture littérale caractère par caractère (suppression de math_format.py et de la normalisation Unicode). - Nouveau profil par défaut 'Mathématiques (LaTeX)' : le modèle émet du LaTeX encadré [EQ]...[/EQ], intercepté par KeyStepper qui déclenche Alt+= en début d'équation et -> en fin. - Config multi-profils dans %APPDATA%/ai-typewriter/config.json (ConfigStore + profils par défaut auto-créés). - Icône de zone de notification (pystray) : Ouvrir les logs (temps réel), Ajouter/Modifier un profil, Gérer l'authentification, Quitter. - Sélecteur de modèles : modèles locaux Ollama + recherche/téléchargement depuis la bibliothèque publique ; fournisseurs tiers (OpenAI, OpenRouter, Gemini, custom). - Clés d'API stockées de façon sécurisée dans le Gestionnaire d'identifiants Windows via keyring (jamais en clair dans config.json). - Tests : 44 tests verts (stepper, profils, clients IA, credentials, catalogue de modèles, moteur).
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
import pytest
|
|
|
|
from ai_typewriter.config import (
|
|
ConfigError,
|
|
ConfigStore,
|
|
Profile,
|
|
load_config,
|
|
math_latex_profile,
|
|
)
|
|
|
|
|
|
def test_store_creates_defaults_when_missing(tmp_path):
|
|
path = tmp_path / "nested" / "config.json"
|
|
store = ConfigStore(path)
|
|
store.ensure_defaults()
|
|
|
|
assert path.exists()
|
|
assert len(store.profiles) == 2
|
|
names = [p.name for p in store.profiles]
|
|
assert "Général" in names
|
|
assert math_latex_profile().name in names
|
|
store.load()
|
|
assert store.active_name in names
|
|
|
|
|
|
def test_default_math_profile_enables_equation_markers():
|
|
p = math_latex_profile()
|
|
assert p.equation_enabled is True
|
|
assert p.eq_start_marker == "[EQ]"
|
|
assert p.eq_end_marker == "[/EQ]"
|
|
assert p.eq_start_key == "alt+="
|
|
assert p.eq_end_key == "right"
|
|
assert "[EQ]" in p.effective_prompt()
|
|
|
|
|
|
def test_crud_upsert_set_active_and_remove(tmp_path):
|
|
path = tmp_path / "config.json"
|
|
store = ConfigStore(path)
|
|
store.ensure_defaults()
|
|
store.load()
|
|
|
|
names_before = len(store.get_all())
|
|
prof = math_latex_profile(name="MaesProfil")
|
|
store.upsert(prof)
|
|
store.set_active("MaesProfil")
|
|
assert store.active().name == "MaesProfil"
|
|
assert len(store.get_all()) == names_before + 1
|
|
|
|
prof2 = Profile(name="MaesProfil", provider="openai", model="gpt-4o-mini")
|
|
store.upsert(prof2)
|
|
assert store.get("MaesProfil").provider == "openai"
|
|
|
|
store.remove("MaesProfil")
|
|
with pytest.raises(KeyError):
|
|
store.get("MaesProfil")
|
|
|
|
|
|
def test_remove_last_profile_blocked(tmp_path):
|
|
store = ConfigStore(tmp_path / "config.json")
|
|
store.ensure_defaults()
|
|
store.load()
|
|
# Il y a 2 profils par défaut : le premier retrait réussit…
|
|
store.remove(store.get_all()[0].name)
|
|
assert len(store.get_all()) == 1
|
|
# …mais retirer le dernier est interdit.
|
|
with pytest.raises(ConfigError):
|
|
store.remove(store.get_all()[0].name)
|
|
|
|
|
|
def test_set_active_unknown_raises(tmp_path):
|
|
store = ConfigStore(tmp_path / "config.json")
|
|
store.ensure_defaults()
|
|
store.load()
|
|
with pytest.raises(KeyError):
|
|
store.set_active("inexistant")
|
|
|
|
|
|
def test_load_config_return_store(tmp_path):
|
|
store = load_config(str(tmp_path / "config.json"))
|
|
assert isinstance(store, ConfigStore) |