import asyncio import io import pytest from fastapi import HTTPException, UploadFile from app.contacts.backend import router_simple from app.services import contact_mail_ai from app.services.email_service import EmailService def test_ai_import_is_review_only_and_preserves_signature_fallback(monkeypatch): parsed = {'sender_name':'Ida Hansen','sender_email':'ida@example.com','body_text':'Mobil: 12345678','subject':'Hej'} monkeypatch.setattr(EmailService,'parse_eml_file',lambda self,content:parsed) async def extract(mail): assert mail is parsed return {'first_name':'Ida','title':'Konsulent'} monkeypatch.setattr(contact_mail_ai,'extract_contact',extract) monkeypatch.setattr(router_simple,'execute_insert',lambda *a,**k:pytest.fail('Must not write')) result=asyncio.run(router_simple.analyze_email_for_new_contact(UploadFile(filename='test.eml',file=io.BytesIO(b'mail')),use_ai=True)) assert result['contact']['title']=='Konsulent' assert result['contact']['email']=='ida@example.com' def test_ai_failure_is_explicit(monkeypatch): monkeypatch.setattr(EmailService,'parse_eml_file',lambda self,content:{'sender_email':'ida@example.com'}) async def fail(mail): raise RuntimeError('secret internal details') monkeypatch.setattr(contact_mail_ai,'extract_contact',fail) with pytest.raises(HTTPException) as error: asyncio.run(router_simple.analyze_email_for_new_contact(UploadFile(filename='test.eml',file=io.BytesIO(b'mail')),use_ai=True)) assert error.value.status_code==502 assert 'secret' not in error.value.detail def test_ai_extract_uses_configured_model_and_limits_fields(monkeypatch): class Response: def raise_for_status(self): pass def json(self): return {'message':{'content':'{"first_name":" Ida ","title":"Support","unknown":"ignore","mobile":1234}'}} class Client: def __init__(self,**kwargs): pass async def __aenter__(self): return self async def __aexit__(self,*args): pass async def post(self,url,json): assert url.endswith('/api/chat') assert json['model']==contact_mail_ai.settings.OLLAMA_MODEL assert json['format']=='json' assert 'sender_email' in json['messages'][1]['content'] return Response() monkeypatch.setattr(contact_mail_ai.httpx,'AsyncClient',Client) result=asyncio.run(contact_mail_ai.extract_contact({'sender_email':'ida@example.com','body_text':'Hej'})) assert result=={'first_name':'Ida','title':'Support'}