Files
int-layer/tests/services/test_quick_reply_content.py
2026-02-20 20:38:59 +00:00

285 lines
9.3 KiB
Python

"""Tests for QuickReplyContentService."""
import json
from unittest.mock import Mock
import pytest
from capa_de_integracion.config import Settings
from capa_de_integracion.models.quick_replies import QuickReplyScreen
from capa_de_integracion.services import QuickReplyContentService
@pytest.fixture
def mock_settings(tmp_path):
"""Create mock settings for testing."""
settings = Mock(spec=Settings)
# Create the quick_replies directory
quick_replies_dir = tmp_path / "quick_replies"
quick_replies_dir.mkdir()
settings.base_path = tmp_path
return settings
@pytest.fixture
def service(mock_settings):
"""Create QuickReplyContentService instance with empty cache."""
return QuickReplyContentService(mock_settings)
@pytest.mark.asyncio
async def test_get_quick_replies_empty_screen_id(service):
"""Test get_quick_replies with empty screen_id."""
result = await service.get_quick_replies("")
assert isinstance(result, QuickReplyScreen)
assert result.header == "empty"
assert result.body is None
assert result.button is None
assert result.header_section is None
assert result.preguntas == []
@pytest.mark.asyncio
async def test_get_quick_replies_none_screen_id(service):
"""Test get_quick_replies with None screen_id."""
result = await service.get_quick_replies(None)
assert isinstance(result, QuickReplyScreen)
assert result.header == "empty"
assert result.preguntas == []
@pytest.mark.asyncio
async def test_get_quick_replies_whitespace_screen_id(service):
"""Test get_quick_replies with whitespace screen_id."""
result = await service.get_quick_replies(" ")
assert isinstance(result, QuickReplyScreen)
assert result.header == "empty"
assert result.preguntas == []
@pytest.mark.asyncio
async def test_get_quick_replies_file_not_found(service):
"""Test get_quick_replies raises error when screen not in cache."""
# Cache is empty (no files loaded), so any screen_id should raise ValueError
with pytest.raises(ValueError, match="Quick reply not found for screen_id"):
await service.get_quick_replies("nonexistent")
@pytest.mark.asyncio
async def test_get_quick_replies_success(tmp_path):
"""Test get_quick_replies successfully retrieves from cache."""
# Create test JSON file BEFORE initializing service
quick_replies_dir = tmp_path / "quick_replies"
quick_replies_dir.mkdir()
test_data = {
"header": "Test Header",
"body": "Test Body",
"button": "Test Button",
"header_section": "Test Section",
"preguntas": [
{
"titulo": "Question 1",
"descripcion": "Description 1",
"respuesta": "Answer 1",
},
{
"titulo": "Question 2",
"respuesta": "Answer 2",
},
],
}
test_file = quick_replies_dir / "test_screen.json"
test_file.write_text(json.dumps(test_data), encoding="utf-8")
# Initialize service - it will preload the file into cache
settings = Mock(spec=Settings)
settings.base_path = tmp_path
service = QuickReplyContentService(settings)
result = await service.get_quick_replies("test_screen")
assert isinstance(result, QuickReplyScreen)
assert result.header == "Test Header"
assert result.body == "Test Body"
assert result.button == "Test Button"
assert result.header_section == "Test Section"
assert len(result.preguntas) == 2
assert result.preguntas[0].titulo == "Question 1"
assert result.preguntas[0].descripcion == "Description 1"
assert result.preguntas[0].respuesta == "Answer 1"
assert result.preguntas[1].titulo == "Question 2"
assert result.preguntas[1].descripcion is None
assert result.preguntas[1].respuesta == "Answer 2"
@pytest.mark.asyncio
async def test_get_quick_replies_invalid_json(tmp_path):
"""Test that invalid JSON files are skipped during cache preload."""
quick_replies_dir = tmp_path / "quick_replies"
quick_replies_dir.mkdir()
# Create invalid JSON file
test_file = quick_replies_dir / "invalid.json"
test_file.write_text("{ invalid json }", encoding="utf-8")
# Initialize service - invalid file should be logged but not crash
settings = Mock(spec=Settings)
settings.base_path = tmp_path
service = QuickReplyContentService(settings)
# Requesting the invalid screen should raise ValueError (not in cache)
with pytest.raises(ValueError, match="Quick reply not found for screen_id"):
await service.get_quick_replies("invalid")
@pytest.mark.asyncio
async def test_get_quick_replies_minimal_data(tmp_path):
"""Test get_quick_replies with minimal data from cache."""
quick_replies_dir = tmp_path / "quick_replies"
quick_replies_dir.mkdir()
test_data = {
"preguntas": [],
}
test_file = quick_replies_dir / "minimal.json"
test_file.write_text(json.dumps(test_data), encoding="utf-8")
# Initialize service - it will preload the file
settings = Mock(spec=Settings)
settings.base_path = tmp_path
service = QuickReplyContentService(settings)
result = await service.get_quick_replies("minimal")
assert isinstance(result, QuickReplyScreen)
assert result.header is None
assert result.body is None
assert result.button is None
assert result.header_section is None
assert result.preguntas == []
@pytest.mark.asyncio
async def test_validate_file_exists(service, tmp_path):
"""Test _validate_file with existing file."""
test_file = tmp_path / "test.json"
test_file.write_text("{}", encoding="utf-8")
# Should not raise
service._validate_file(test_file, "test")
@pytest.mark.asyncio
async def test_validate_file_not_exists(service, tmp_path):
"""Test _validate_file with non-existing file."""
test_file = tmp_path / "nonexistent.json"
with pytest.raises(ValueError, match="Quick reply file not found"):
service._validate_file(test_file, "test")
@pytest.mark.asyncio
async def test_cache_preload_multiple_files(tmp_path):
"""Test that cache preloads multiple files correctly."""
quick_replies_dir = tmp_path / "quick_replies"
quick_replies_dir.mkdir()
# Create multiple test files
for screen_id in ["home", "pagos", "transferencia"]:
test_data = {
"header": f"{screen_id} header",
"preguntas": [
{"titulo": f"Q1 for {screen_id}", "respuesta": "Answer 1"},
],
}
test_file = quick_replies_dir / f"{screen_id}.json"
test_file.write_text(json.dumps(test_data), encoding="utf-8")
# Initialize service
settings = Mock(spec=Settings)
settings.base_path = tmp_path
service = QuickReplyContentService(settings)
# Verify all screens are in cache
home = await service.get_quick_replies("home")
assert home.header == "home header"
pagos = await service.get_quick_replies("pagos")
assert pagos.header == "pagos header"
transferencia = await service.get_quick_replies("transferencia")
assert transferencia.header == "transferencia header"
@pytest.mark.asyncio
async def test_cache_preload_with_mixed_valid_invalid(tmp_path):
"""Test cache preload handles mix of valid and invalid files."""
quick_replies_dir = tmp_path / "quick_replies"
quick_replies_dir.mkdir()
# Create valid file
valid_data = {"header": "valid", "preguntas": []}
(quick_replies_dir / "valid.json").write_text(
json.dumps(valid_data), encoding="utf-8",
)
# Create invalid file
(quick_replies_dir / "invalid.json").write_text(
"{ invalid }", encoding="utf-8",
)
# Initialize service - should not crash
settings = Mock(spec=Settings)
settings.base_path = tmp_path
service = QuickReplyContentService(settings)
# Valid file should be in cache
valid = await service.get_quick_replies("valid")
assert valid.header == "valid"
# Invalid file should not be in cache
with pytest.raises(ValueError, match="Quick reply not found"):
await service.get_quick_replies("invalid")
@pytest.mark.asyncio
async def test_cache_preload_handles_generic_exception(tmp_path, monkeypatch):
"""Test cache preload handles generic exceptions during file processing."""
from pathlib import Path
from unittest.mock import Mock
quick_replies_dir = tmp_path / "quick_replies"
quick_replies_dir.mkdir()
# Create valid JSON file
valid_data = {"header": "test", "preguntas": []}
(quick_replies_dir / "test.json").write_text(
json.dumps(valid_data), encoding="utf-8",
)
# Mock _parse_quick_reply_data to raise generic exception
def mock_parse_error(*args, **kwargs):
raise ValueError("Simulated parsing error")
settings = Mock(spec=Settings)
settings.base_path = tmp_path
# Initialize service and patch the parsing method
with monkeypatch.context() as m:
service = QuickReplyContentService(settings)
m.setattr(service, "_parse_quick_reply_data", mock_parse_error)
# Manually call _preload_cache to trigger the exception
service._cache.clear()
service._preload_cache()
# The file should not be in cache due to the exception
with pytest.raises(ValueError, match="Quick reply not found"):
await service.get_quick_replies("test")