|
13 | 13 | get_feedback_title,
|
14 | 14 | validate_issue_platform_event_schema,
|
15 | 15 | )
|
| 16 | +from sentry.feedback.usecases.label_generation import AI_LABEL_TAG_PREFIX, MAX_AI_LABELS |
16 | 17 | from sentry.models.group import Group, GroupStatus
|
17 | 18 | from sentry.signals import first_feedback_received, first_new_feedback_received
|
18 | 19 | from sentry.testutils.helpers import Feature
|
@@ -935,3 +936,118 @@ def test_create_feedback_issue_title(default_project, mock_produce_occurrence_to
|
935 | 936 | "User Feedback: This is a very long feedback message that describes multiple..."
|
936 | 937 | )
|
937 | 938 | assert occurrence.issue_title == expected_title
|
| 939 | + |
| 940 | + |
| 941 | +@django_db_all |
| 942 | +def test_create_feedback_adds_ai_labels( |
| 943 | + default_project, mock_produce_occurrence_to_kafka, monkeypatch |
| 944 | +): |
| 945 | + """Test that create_feedback_issue adds AI labels to tags when label generation succeeds.""" |
| 946 | + with Feature( |
| 947 | + { |
| 948 | + "organizations:user-feedback-ai-categorization": True, |
| 949 | + "organizations:gen-ai-features": True, |
| 950 | + } |
| 951 | + ): |
| 952 | + event = mock_feedback_event(default_project.id) |
| 953 | + event["contexts"]["feedback"]["message"] = "The login button is broken and the UI is slow" |
| 954 | + |
| 955 | + # This assumes that the maximum number of labels allowed is greater than 3 |
| 956 | + def mock_generate_labels(*args, **kwargs): |
| 957 | + return ["User Interface", "Authentication", "Performance"] |
| 958 | + |
| 959 | + monkeypatch.setattr( |
| 960 | + "sentry.feedback.usecases.ingest.create_feedback.generate_labels", |
| 961 | + mock_generate_labels, |
| 962 | + ) |
| 963 | + |
| 964 | + create_feedback_issue(event, default_project, FeedbackCreationSource.NEW_FEEDBACK_ENVELOPE) |
| 965 | + |
| 966 | + assert mock_produce_occurrence_to_kafka.call_count == 1 |
| 967 | + produced_event = mock_produce_occurrence_to_kafka.call_args.kwargs["event_data"] |
| 968 | + tags = produced_event["tags"] |
| 969 | + |
| 970 | + ai_labels = [value for key, value in tags.items() if key.startswith(AI_LABEL_TAG_PREFIX)] |
| 971 | + assert len(ai_labels) == 3 |
| 972 | + assert set(ai_labels) == {"User Interface", "Authentication", "Performance"} |
| 973 | + |
| 974 | + |
| 975 | +@django_db_all |
| 976 | +def test_create_feedback_handles_label_generation_errors( |
| 977 | + default_project, mock_produce_occurrence_to_kafka, monkeypatch |
| 978 | +): |
| 979 | + """Test that create_feedback_issue continues to work even when generate_labels raises an error.""" |
| 980 | + with Feature( |
| 981 | + { |
| 982 | + "organizations:user-feedback-ai-categorization": True, |
| 983 | + "organizations:gen-ai-features": True, |
| 984 | + } |
| 985 | + ): |
| 986 | + event = mock_feedback_event(default_project.id) |
| 987 | + event["contexts"]["feedback"]["message"] = "This is a valid feedback message" |
| 988 | + |
| 989 | + # Mock generate_labels to raise an exception |
| 990 | + def mock_generate_labels(*args, **kwargs): |
| 991 | + raise Exception("Label generation failed") |
| 992 | + |
| 993 | + monkeypatch.setattr( |
| 994 | + "sentry.feedback.usecases.ingest.create_feedback.generate_labels", |
| 995 | + mock_generate_labels, |
| 996 | + ) |
| 997 | + |
| 998 | + # This should not raise an exception and should still create the feedback |
| 999 | + create_feedback_issue(event, default_project, FeedbackCreationSource.NEW_FEEDBACK_ENVELOPE) |
| 1000 | + |
| 1001 | + # Verify that the feedback was still created successfully |
| 1002 | + assert mock_produce_occurrence_to_kafka.call_count == 1 |
| 1003 | + |
| 1004 | + produced_event = mock_produce_occurrence_to_kafka.call_args.kwargs["event_data"] |
| 1005 | + tags = produced_event["tags"] |
| 1006 | + |
| 1007 | + ai_labels = [tag for tag in tags.keys() if tag.startswith(AI_LABEL_TAG_PREFIX)] |
| 1008 | + assert ( |
| 1009 | + len(ai_labels) == 0 |
| 1010 | + ), "No AI categorization labels should be present when label generation fails" |
| 1011 | + |
| 1012 | + |
| 1013 | +@django_db_all |
| 1014 | +def test_create_feedback_truncates_ai_labels( |
| 1015 | + default_project, mock_produce_occurrence_to_kafka, monkeypatch |
| 1016 | +): |
| 1017 | + """Test that create_feedback_issue truncates AI labels when more than MAX_AI_LABELS are returned.""" |
| 1018 | + with Feature( |
| 1019 | + { |
| 1020 | + "organizations:user-feedback-ai-categorization": True, |
| 1021 | + "organizations:gen-ai-features": True, |
| 1022 | + } |
| 1023 | + ): |
| 1024 | + event = mock_feedback_event(default_project.id) |
| 1025 | + event["contexts"]["feedback"][ |
| 1026 | + "message" |
| 1027 | + ] = "This is a very complex feedback with many issues" |
| 1028 | + |
| 1029 | + # Mock generate_labels to return more than MAX_AI_LABELS labels |
| 1030 | + def mock_generate_labels(*args, **kwargs): |
| 1031 | + return [f"Label {i}" for i in range(MAX_AI_LABELS + 5)] |
| 1032 | + |
| 1033 | + monkeypatch.setattr( |
| 1034 | + "sentry.feedback.usecases.ingest.create_feedback.generate_labels", |
| 1035 | + mock_generate_labels, |
| 1036 | + ) |
| 1037 | + |
| 1038 | + create_feedback_issue(event, default_project, FeedbackCreationSource.NEW_FEEDBACK_ENVELOPE) |
| 1039 | + |
| 1040 | + assert mock_produce_occurrence_to_kafka.call_count == 1 |
| 1041 | + |
| 1042 | + produced_event = mock_produce_occurrence_to_kafka.call_args.kwargs["event_data"] |
| 1043 | + tags = produced_event["tags"] |
| 1044 | + |
| 1045 | + ai_labels = [value for key, value in tags.items() if key.startswith(AI_LABEL_TAG_PREFIX)] |
| 1046 | + assert len(ai_labels) == MAX_AI_LABELS, "Should be truncated to exactly MAX_AI_LABELS" |
| 1047 | + |
| 1048 | + for i in range(MAX_AI_LABELS): |
| 1049 | + assert tags[f"{AI_LABEL_TAG_PREFIX}.{i}"] == f"Label {i}" |
| 1050 | + |
| 1051 | + # Verify that labels beyond MAX_AI_LABELS are not present |
| 1052 | + for i in range(MAX_AI_LABELS, MAX_AI_LABELS + 5): |
| 1053 | + assert f"{AI_LABEL_TAG_PREFIX}.{i}" not in tags |
0 commit comments