"""Tests du stockage sécurisé (keyring mocké pour éviter tout accès au gestionnaire d'identifiants réel de la machine).""" import pytest from ai_typewriter.credentials import CredentialError, SecureStore, get_cred class FakeKeyring: """Mini stub de keyring en mémoire, exposant la même interface.""" _data = {} @classmethod def reset(cls): cls._data = {} @classmethod def set_password(cls, service, username, password): cls._data[(service, username)] = password @classmethod def get_password(cls, service, username): return cls._data.get((service, username)) @classmethod def delete_password(cls, service, username): cls._data.pop((service, username), None) class FakeKeyringErrors: class PasswordDeleteError(RuntimeError): pass def test_store_and_get(monkeypatch): import ai_typewriter.credentials as cred monkeypatch.setattr(cred, "keyring", FakeKeyring) monkeypatch.setattr(cred.keyring, "errors", FakeKeyringErrors, raising=False) FakeKeyring.reset() store = SecureStore("test-service") store.store("openai", "sk-secret") assert store.get("openai") == "sk-secret" assert store.has("openai") is True def test_empty_credential_returns_empty(monkeypatch): import ai_typewriter.credentials as cred monkeypatch.setattr(cred, "keyring", FakeKeyring) FakeKeyring.reset() store = SecureStore() assert store.get("") == "" assert store.has("") is False def test_get_cred_helper_creates_store(monkeypatch): import ai_typewriter.credentials as cred monkeypatch.setattr(cred, "keyring", FakeKeyring) monkeypatch.setattr(cred.keyring, "errors", FakeKeyringErrors, raising=False) FakeKeyring.reset() # via un store passé explicitement store = SecureStore("t") store.store("k", "v") assert get_cred(store, "k") == "v" # via None (crée un store par défaut, mais retombe sur service réel) — # on vérifie que quelques accesseurs ne plantent pas. assert get_cred(None, "") == "" def test_store_invalid_credential_name(monkeypatch): import ai_typewriter.credentials as cred monkeypatch.setattr(cred, "keyring", FakeKeyring) FakeKeyring.reset() store = SecureStore() with pytest.raises(CredentialError): store.store("", "secret") def test_delete(monkeypatch): import ai_typewriter.credentials as cred monkeypatch.setattr(cred, "keyring", FakeKeyring) monkeypatch.setattr(cred.keyring, "errors", FakeKeyringErrors, raising=False) FakeKeyring.reset() store = SecureStore("t") store.store("gemini", "cle") store.delete("gemini") assert store.has("gemini") is False