@@ -85,9 +85,6 @@ async def test_chat_empty_body(client):
8585 )
8686
8787 assert response .status_code == 400
88- data = await response .get_json ()
89- assert data ["action_type" ] == "error"
90- assert "required" in data ["message" ].lower ()
9188
9289
9390@pytest .mark .asyncio
@@ -103,6 +100,35 @@ async def test_chat_whitespace_message(client):
103100 assert data ["action_type" ] == "error"
104101
105102
103+ @pytest .mark .asyncio
104+ async def test_chat_null_message (client ):
105+ """Test chat endpoint handles null message without crashing."""
106+ response = await client .post (
107+ "/api/chat" ,
108+ json = {"conversation_id" : "test-conv" , "message" : None }
109+ )
110+
111+ assert response .status_code == 400
112+ data = await response .get_json ()
113+ assert data ["action_type" ] == "error"
114+ assert "empty" in data ["message" ].lower ()
115+
116+
117+ @pytest .mark .asyncio
118+ async def test_chat_invalid_json_body (client ):
119+ """Test chat endpoint rejects invalid JSON body with 400."""
120+ response = await client .post (
121+ "/api/chat" ,
122+ data = "not valid json" ,
123+ headers = {"Content-Type" : "application/json" }
124+ )
125+
126+ assert response .status_code == 400
127+ data = await response .get_json ()
128+ assert data ["action_type" ] == "error"
129+ assert "required" in data ["message" ].lower ()
130+
131+
106132@pytest .mark .asyncio
107133async def test_chat_empty_message_with_action_allowed (client ):
108134 """Test chat endpoint allows empty message when action is specified."""
@@ -229,36 +255,15 @@ async def test_chat_cosmos_failure(client):
229255
230256@pytest .mark .asyncio
231257async def test_parse_brief_missing_text (client ):
232- """Test chat endpoint with missing message still processes (no validation)."""
233- with patch ("app.get_routing_service" ) as mock_routing , \
234- patch ("app.get_cosmos_service" ) as mock_cosmos , \
235- patch ("app.get_orchestrator" ) as mock_orch :
236-
237- from services .routing_service import Intent , RoutingResult , ConversationState
238- mock_routing_service = MagicMock ()
239- mock_routing_service .classify_intent = MagicMock (return_value = RoutingResult (
240- intent = Intent .PARSE_BRIEF ,
241- confidence = 0.5
242- ))
243- mock_routing_service .derive_state_from_conversation = MagicMock (return_value = ConversationState ())
244- mock_routing .return_value = mock_routing_service
245-
246- mock_cosmos_service = AsyncMock ()
247- mock_cosmos_service .get_conversation = AsyncMock (return_value = None )
248- mock_cosmos_service .add_message_to_conversation = AsyncMock ()
249- mock_cosmos .return_value = mock_cosmos_service
250-
251- mock_orchestrator = AsyncMock ()
252- mock_orchestrator .parse_brief = AsyncMock (return_value = (MagicMock (model_dump = lambda : {}), None , False ))
253- mock_orch .return_value = mock_orchestrator
254-
255- response = await client .post (
256- "/api/chat" ,
257- json = {"conversation_id" : "test-conv" }
258- )
258+ """Test chat endpoint rejects missing message with 400."""
259+ response = await client .post (
260+ "/api/chat" ,
261+ json = {"conversation_id" : "test-conv" }
262+ )
259263
260- # API doesn't validate missing message - routes to handler with empty message
261- assert response .status_code in [200 , 500 ]
264+ assert response .status_code == 400
265+ data = await response .get_json ()
266+ assert data ["action_type" ] == "error"
262267
263268
264269@pytest .mark .asyncio
@@ -906,39 +911,17 @@ async def test_regenerate_content_success(client, sample_creative_brief_dict):
906911
907912@pytest .mark .asyncio
908913async def test_regenerate_content_missing_modification_request (client , sample_creative_brief_dict ):
909- """Test regeneration without message still routes (no validation)."""
910- with patch ("app.get_routing_service" ) as mock_routing , \
911- patch ("app.get_cosmos_service" ) as mock_cosmos , \
912- patch ("app.get_orchestrator" ) as mock_orch :
913-
914- from services .routing_service import Intent , RoutingResult , ConversationState
915- mock_routing_service = MagicMock ()
916- mock_routing_service .classify_intent = MagicMock (return_value = RoutingResult (
917- intent = Intent .PARSE_BRIEF ,
918- confidence = 0.5
919- ))
920- mock_routing_service .derive_state_from_conversation = MagicMock (return_value = ConversationState ())
921- mock_routing .return_value = mock_routing_service
922-
923- mock_cosmos_service = AsyncMock ()
924- mock_cosmos_service .get_conversation = AsyncMock (return_value = None )
925- mock_cosmos_service .add_message_to_conversation = AsyncMock ()
926- mock_cosmos .return_value = mock_cosmos_service
927-
928- mock_orchestrator = AsyncMock ()
929- mock_orchestrator .parse_brief = AsyncMock (return_value = (MagicMock (model_dump = lambda : {}), None , False ))
930- mock_orch .return_value = mock_orchestrator
931-
932- response = await client .post (
933- "/api/chat" ,
934- json = {
935- "conversation_id" : "test-conv"
936- # Missing message - no validation in backend
937- }
938- )
914+ """Test regeneration rejects missing message with 400."""
915+ response = await client .post (
916+ "/api/chat" ,
917+ json = {
918+ "conversation_id" : "test-conv"
919+ }
920+ )
939921
940- # Backend doesn't validate missing message
941- assert response .status_code in [200 , 500 ]
922+ assert response .status_code == 400
923+ data = await response .get_json ()
924+ assert data ["action_type" ] == "error"
942925
943926
944927@pytest .mark .asyncio
0 commit comments