Skip to content

Commit 24a3d12

Browse files
authored
Merge pull request lightspeed-core#711 from asimurka/fix_nonempty_feedback_must_be_provided
LCORE-755: Fixed feedback endpoint responds correctly without sentiment and empty user_feedback
2 parents aa3d770 + af7de68 commit 24a3d12

4 files changed

Lines changed: 75 additions & 3 deletions

File tree

src/models/requests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ def check_feedback_provided(self) -> Self:
377377
"""Ensure that at least one form of feedback is provided."""
378378
if (
379379
self.sentiment is None
380-
and self.user_feedback is None
380+
and (self.user_feedback is None or self.user_feedback == "")
381381
and self.categories is None
382382
):
383383
raise ValueError(

tests/e2e/features/feedback.feature

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,4 +306,31 @@ Feature: feedback endpoint API tests
306306
"cause": "[Errno 13] Permission denied: '/invalid'"
307307
}
308308
}
309-
"""
309+
"""
310+
311+
Scenario: Check if feedback endpoint fails when only empty string user_feedback is provided
312+
Given The system is in default state
313+
And A new conversation is initialized
314+
And The feedback is enabled
315+
When I submit the following feedback for the conversation created before
316+
"""
317+
{
318+
"user_question": "Sample Question",
319+
"llm_response": "Sample Response",
320+
"user_feedback": ""
321+
}
322+
"""
323+
Then The status code of the response is 422
324+
And the body of the response has the following structure
325+
"""
326+
{
327+
"detail": [{
328+
"type": "value_error",
329+
"loc": ["body"],
330+
"msg": "Value error, At least one form of feedback must be provided: 'sentiment', 'user_feedback', or 'categories'",
331+
"input": {
332+
"user_feedback": ""
333+
}
334+
}]
335+
}
336+
"""

tests/unit/app/endpoints/test_feedback.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@
1212
store_feedback,
1313
update_feedback_status,
1414
)
15-
from models.requests import FeedbackStatusUpdateRequest
15+
from models.requests import FeedbackStatusUpdateRequest, FeedbackRequest
1616
from tests.unit.utils.auth_helpers import mock_authorization_resolvers
1717

1818

19+
MOCK_AUTH = ("mock_user_id", "mock_username", False, "mock_token")
20+
VALID_BASE = {
21+
"conversation_id": "12345678-abcd-0000-0123-456789abcdef",
22+
"user_question": "What is Kubernetes?",
23+
"llm_response": "Kubernetes is an open-source container orchestration system.",
24+
}
25+
26+
1927
def test_is_feedback_enabled():
2028
"""Test that is_feedback_enabled returns True when feedback is not disabled."""
2129
configuration.user_data_collection_configuration.feedback_enabled = True
@@ -230,3 +238,26 @@ async def test_update_feedback_status_no_change(mocker: MockerFixture):
230238
"updated_by": "test_user_id",
231239
"timestamp": mocker.ANY,
232240
}
241+
242+
243+
@pytest.mark.parametrize(
244+
"payload",
245+
[
246+
{"sentiment": -1},
247+
{"user_feedback": "Good answer"},
248+
{"categories": ["incorrect"]},
249+
],
250+
ids=["test_sentiment_only", "test_user_feedback_only", "test_categories_only"],
251+
)
252+
@pytest.mark.asyncio
253+
async def test_feedback_endpoint_valid_requests(mocker: MockerFixture, payload):
254+
"""Test endpoint with valid feedback payloads."""
255+
mock_authorization_resolvers(mocker)
256+
mocker.patch("app.endpoints.feedback.store_feedback")
257+
request = FeedbackRequest(**{**VALID_BASE, **payload})
258+
response = await feedback_endpoint_handler(
259+
feedback_request=request,
260+
auth=MOCK_AUTH,
261+
_ensure_feedback_enabled=None,
262+
)
263+
assert response.response == "feedback received"

tests/unit/models/requests/test_feedback_request.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,17 @@ def test_categories_invalid_type(self) -> None:
182182
llm_response="Test response",
183183
categories="invalid_type", # Should be list, not string
184184
)
185+
186+
def test_empty_user_feedback_not_sufficient(self) -> None:
187+
"""Test that an empty string for user_feedback is treated as no feedback."""
188+
with pytest.raises(
189+
ValueError, match="At least one form of feedback must be provided"
190+
):
191+
FeedbackRequest(
192+
conversation_id="123e4567-e89b-12d3-a456-426614174000",
193+
user_question="What is feedback?",
194+
llm_response="Some LLM response.",
195+
user_feedback="", # Empty string should trigger validation error
196+
sentiment=None,
197+
categories=None,
198+
)

0 commit comments

Comments
 (0)