fix: webhook test modernization and production bug fix
- Fix production bug in send_whatsapp_message: access 'instance_url' instead of 'server_url' to match SendMessageScheme TypedDict definition - Update webhook test to use test_app with in-memory dependencies - Mock send_whatsapp_message to avoid real HTTP calls in tests - Add assertions to verify correct parameters passed to send_whatsapp_message Bug: send_whatsapp_message accessed request_data['server_url'] but SendMessageScheme defines field as 'instance_url', causing KeyError when webhook tries to send WhatsApp messages.
This commit is contained in:
@@ -15,7 +15,9 @@ from naliiabot.bot.prompts.load_prompt import get_prompt_template
|
||||
from naliiabot.bot.tools.naliia_tools import NaliiaTools
|
||||
import naliiabotapi.api.dependencies as deps
|
||||
from naliiabotapi.api.v1.endpoints.chat import router as chat_router
|
||||
from naliiabotapi.api.v1.webhooks.chat_hook import router as chat_hook_router
|
||||
from naliiabotapi.api.v1.webhooks.chat_hook import (
|
||||
router as chat_hook_router,
|
||||
)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
@@ -23,31 +25,33 @@ async def test_lifespan(app: FastAPI):
|
||||
"""Test lifespan that uses in-memory checkpointer instead of PostgreSQL."""
|
||||
# Use in-memory checkpointer for tests
|
||||
checkpointer = MemorySaver()
|
||||
|
||||
|
||||
# Use a mock model for tests to avoid needing API keys
|
||||
# The mock needs to return proper AIMessage objects
|
||||
mock_model = MagicMock()
|
||||
|
||||
|
||||
def mock_invoke(*args, **kwargs):
|
||||
"""Mock invoke that returns a proper AIMessage."""
|
||||
return AIMessage(content="This is a test response from the mock model.")
|
||||
|
||||
return AIMessage(
|
||||
content="This is a test response from the mock model."
|
||||
)
|
||||
|
||||
mock_model.invoke = mock_invoke
|
||||
mock_model.bind_tools = Mock(return_value=mock_model)
|
||||
|
||||
|
||||
naliia_prompt = get_prompt_template("NALIIA_PROMPT")
|
||||
naliia_tools = NaliiaTools().get_tools()
|
||||
config = AgentConfig(system_prompt=naliia_prompt)
|
||||
|
||||
|
||||
deps.agent_instance = Agent(
|
||||
model=mock_model,
|
||||
config=config,
|
||||
checkpointer=checkpointer,
|
||||
tools=naliia_tools,
|
||||
)
|
||||
|
||||
|
||||
yield
|
||||
|
||||
|
||||
# Cleanup
|
||||
deps.agent_instance = None
|
||||
|
||||
@@ -62,18 +66,18 @@ def test_app():
|
||||
root_path="/agent/api",
|
||||
lifespan=test_lifespan,
|
||||
)
|
||||
|
||||
|
||||
app.include_router(chat_router)
|
||||
app.include_router(chat_hook_router)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health_check():
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
return app
|
||||
|
||||
|
||||
@@ -83,7 +87,7 @@ async def async_client(test_app):
|
||||
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=test_app),
|
||||
base_url="http://localhost:8010"
|
||||
base_url="http://localhost:8010",
|
||||
) as client:
|
||||
|
||||
yield client
|
||||
@@ -110,9 +114,7 @@ def mock_model():
|
||||
def default_config():
|
||||
"""Configuración de test predecible."""
|
||||
return AgentConfig(
|
||||
system_prompt="Test prompt",
|
||||
max_iterations=5,
|
||||
timeout_seconds=10.0
|
||||
system_prompt="Test prompt", max_iterations=5, timeout_seconds=10.0
|
||||
)
|
||||
|
||||
|
||||
@@ -126,9 +128,7 @@ def agent(mock_model, default_config):
|
||||
def agent_with_tool(mock_model, default_config, mock_tool):
|
||||
"""Agente con una herramienta mock."""
|
||||
return Agent(
|
||||
model=mock_model,
|
||||
config=default_config,
|
||||
tools=[mock_tool]
|
||||
model=mock_model, config=default_config, tools=[mock_tool]
|
||||
)
|
||||
|
||||
|
||||
@@ -150,8 +150,10 @@ def send_message_payload():
|
||||
"key": {
|
||||
"remoteJid": "5512992544490@s.whatsapp.net",
|
||||
"remoteJidAlt": "5512992544490@s.whatsapp.net",
|
||||
"fromMe": False, "id": "AC4367597BDC50537133B9C8848B2E62",
|
||||
"participant": "", "addressingMode": "lid"
|
||||
"fromMe": False,
|
||||
"id": "AC4367597BDC50537133B9C8848B2E62",
|
||||
"participant": "",
|
||||
"addressingMode": "lid",
|
||||
},
|
||||
"pushName": "Alejandro",
|
||||
"status": "DELIVERY_ACK",
|
||||
@@ -172,12 +174,12 @@ def send_message_payload():
|
||||
"6": 172,
|
||||
"7": 243,
|
||||
"8": 27,
|
||||
"9": 98
|
||||
"9": 98,
|
||||
},
|
||||
"senderTimestamp": {
|
||||
"low": 1772156772,
|
||||
"high": 0,
|
||||
"unsigned": "true"
|
||||
"unsigned": "true",
|
||||
},
|
||||
"recipientKeyHash": {
|
||||
"0": 16,
|
||||
@@ -189,13 +191,13 @@ def send_message_payload():
|
||||
"6": 24,
|
||||
"7": 225,
|
||||
"8": 244,
|
||||
"9": 126
|
||||
"9": 126,
|
||||
},
|
||||
"recipientTimestamp": {
|
||||
"low": 1772155597,
|
||||
"high": 0,
|
||||
"unsigned": True
|
||||
}
|
||||
"unsigned": True,
|
||||
},
|
||||
},
|
||||
"deviceListMetadataVersion": 2,
|
||||
"messageSecret": {
|
||||
@@ -230,18 +232,20 @@ def send_message_payload():
|
||||
"28": 87,
|
||||
"29": 176,
|
||||
"30": 135,
|
||||
"31": 62
|
||||
}}},
|
||||
"31": 62,
|
||||
},
|
||||
},
|
||||
},
|
||||
"messageType": "conversation",
|
||||
"messageTimestamp": 1772168493,
|
||||
"instanceId": "75a877f1-d772-422b-a6f1-6ac470af5663",
|
||||
"source": "android"
|
||||
"source": "android",
|
||||
},
|
||||
"destination": "http://192.168.58.110:8010/webhook",
|
||||
"date_time": "2026-02-27T02:01:34.178Z",
|
||||
"sender": "573016859278@s.whatsapp.net",
|
||||
"server_url": "http://localhost:8080",
|
||||
"apikey": "98B6B820AFC3-4544-9A4C-011B0719C2D1"
|
||||
"apikey": "98B6B820AFC3-4544-9A4C-011B0719C2D1",
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user