106 lines
3.5 KiB
Python
106 lines
3.5 KiB
Python
from core import ai_fetch
|
|
|
|
|
|
class _FakeMessage:
|
|
def __init__(self, content, annotations=None):
|
|
self.content = content
|
|
self.annotations = annotations
|
|
|
|
|
|
class _FakeChoice:
|
|
def __init__(self, message):
|
|
self.message = message
|
|
|
|
|
|
class _FakeResponse:
|
|
def __init__(self, message):
|
|
self.choices = [_FakeChoice(message)]
|
|
|
|
|
|
def test_fetch_with_ai_returns_result_when_content_sufficient(monkeypatch):
|
|
class _FakeClient:
|
|
class chat:
|
|
class completions:
|
|
@staticmethod
|
|
def create(**kwargs):
|
|
return _FakeResponse(_FakeMessage('x' * 400))
|
|
|
|
monkeypatch.setattr(ai_fetch, 'OpenAI', lambda api_key, base_url: _FakeClient())
|
|
|
|
result = ai_fetch.fetch_with_ai('https://intrepidtravel.com/peru')
|
|
|
|
assert result['success'] is True
|
|
assert result['char_count'] == 400
|
|
|
|
|
|
def test_fetch_with_ai_returns_none_when_content_too_short(monkeypatch):
|
|
class _FakeClient:
|
|
class chat:
|
|
class completions:
|
|
@staticmethod
|
|
def create(**kwargs):
|
|
return _FakeResponse(_FakeMessage('too short'))
|
|
|
|
monkeypatch.setattr(ai_fetch, 'OpenAI', lambda api_key, base_url: _FakeClient())
|
|
|
|
assert ai_fetch.fetch_with_ai('https://intrepidtravel.com/peru') is None
|
|
|
|
|
|
def test_fetch_with_ai_returns_none_on_exception(monkeypatch):
|
|
class _FakeClient:
|
|
class chat:
|
|
class completions:
|
|
@staticmethod
|
|
def create(**kwargs):
|
|
raise Exception('api down')
|
|
|
|
monkeypatch.setattr(ai_fetch, 'OpenAI', lambda api_key, base_url: _FakeClient())
|
|
|
|
assert ai_fetch.fetch_with_ai('https://intrepidtravel.com/peru') is None
|
|
|
|
|
|
def test_fetch_with_ai_appends_citation_content(monkeypatch):
|
|
citation = type('Citation', (), {'content': 'extra citation text'})()
|
|
annotation = type('Annotation', (), {'url_citation': citation})()
|
|
|
|
class _FakeClient:
|
|
class chat:
|
|
class completions:
|
|
@staticmethod
|
|
def create(**kwargs):
|
|
return _FakeResponse(_FakeMessage('x' * 350, annotations=[annotation]))
|
|
|
|
monkeypatch.setattr(ai_fetch, 'OpenAI', lambda api_key, base_url: _FakeClient())
|
|
|
|
result = ai_fetch.fetch_with_ai('https://intrepidtravel.com/peru')
|
|
assert 'extra citation text' in result['text']
|
|
|
|
|
|
def test_fetch_with_ai_prompt_forbids_markdown_and_scopes_to_single_page(monkeypatch):
|
|
"""
|
|
Regression test — a real failure showed gpt-4o-mini defaulting to a
|
|
markdown-formatted, multi-trip summary of the whole domain when the
|
|
prompt didn't explicitly forbid that. The resulting markdown then
|
|
confused the downstream extraction model (build_prompt()'s "Return
|
|
ONLY a valid JSON object, no markdown" instruction) into producing
|
|
unparseable output. The prompt sent here must explicitly rule both
|
|
of those out.
|
|
"""
|
|
captured = {}
|
|
|
|
class _FakeClient:
|
|
class chat:
|
|
class completions:
|
|
@staticmethod
|
|
def create(**kwargs):
|
|
captured['messages'] = kwargs['messages']
|
|
return _FakeResponse(_FakeMessage('x' * 400))
|
|
|
|
monkeypatch.setattr(ai_fetch, 'OpenAI', lambda api_key, base_url: _FakeClient())
|
|
|
|
ai_fetch.fetch_with_ai('https://intrepidtravel.com/peru')
|
|
|
|
prompt_text = captured['messages'][0]['content']
|
|
assert 'no markdown' in prompt_text.lower()
|
|
assert 'this exact url' in prompt_text.lower() or 'this one tour' in prompt_text.lower()
|