| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775 |
- from unittest.mock import patch
- import pytest
- from faker import Faker
- from models.model import MessageFeedback
- from services.app_service import AppService
- from services.errors.message import (
- FirstMessageNotExistsError,
- LastMessageNotExistsError,
- MessageNotExistsError,
- SuggestedQuestionsAfterAnswerDisabledError,
- )
- from services.message_service import MessageService
- class TestMessageService:
- """Integration tests for MessageService using testcontainers."""
- @pytest.fixture
- def mock_external_service_dependencies(self):
- """Mock setup for external service dependencies."""
- with (
- patch("services.account_service.FeatureService") as mock_account_feature_service,
- patch("services.message_service.ModelManager") as mock_model_manager,
- patch("services.message_service.WorkflowService") as mock_workflow_service,
- patch("services.message_service.AdvancedChatAppConfigManager") as mock_app_config_manager,
- patch("services.message_service.LLMGenerator") as mock_llm_generator,
- patch("services.message_service.TraceQueueManager") as mock_trace_manager_class,
- patch("services.message_service.TokenBufferMemory") as mock_token_buffer_memory,
- ):
- # Setup default mock returns
- mock_account_feature_service.get_features.return_value.billing.enabled = False
- # Mock ModelManager
- mock_model_instance = mock_model_manager.return_value.get_default_model_instance.return_value
- mock_model_instance.get_tts_voices.return_value = [{"value": "test-voice"}]
- # Mock get_model_instance method as well
- mock_model_manager.return_value.get_model_instance.return_value = mock_model_instance
- # Mock WorkflowService
- mock_workflow = mock_workflow_service.return_value.get_published_workflow.return_value
- mock_workflow_service.return_value.get_draft_workflow.return_value = mock_workflow
- # Mock AdvancedChatAppConfigManager
- mock_app_config = mock_app_config_manager.get_app_config.return_value
- mock_app_config.additional_features.suggested_questions_after_answer = True
- # Mock LLMGenerator
- mock_llm_generator.generate_suggested_questions_after_answer.return_value = ["Question 1", "Question 2"]
- # Mock TraceQueueManager
- mock_trace_manager_instance = mock_trace_manager_class.return_value
- # Mock TokenBufferMemory
- mock_memory_instance = mock_token_buffer_memory.return_value
- mock_memory_instance.get_history_prompt_text.return_value = "Mocked history prompt"
- yield {
- "account_feature_service": mock_account_feature_service,
- "model_manager": mock_model_manager,
- "workflow_service": mock_workflow_service,
- "app_config_manager": mock_app_config_manager,
- "llm_generator": mock_llm_generator,
- "trace_manager_class": mock_trace_manager_class,
- "trace_manager_instance": mock_trace_manager_instance,
- "token_buffer_memory": mock_token_buffer_memory,
- # "current_user": mock_current_user,
- }
- def _create_test_app_and_account(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Helper method to create a test app and account for testing.
- Args:
- db_session_with_containers: Database session from testcontainers infrastructure
- mock_external_service_dependencies: Mock dependencies
- Returns:
- tuple: (app, account) - Created app and account instances
- """
- fake = Faker()
- # Setup mocks for account creation
- mock_external_service_dependencies[
- "account_feature_service"
- ].get_system_features.return_value.is_allow_register = True
- # Create account and tenant first
- from services.account_service import AccountService, TenantService
- account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(account, name=fake.company())
- tenant = account.current_tenant
- # Setup app creation arguments
- app_args = {
- "name": fake.company(),
- "description": fake.text(max_nb_chars=100),
- "mode": "advanced-chat", # Use advanced-chat mode to use mocked workflow
- "icon_type": "emoji",
- "icon": "📚",
- "icon_background": "#FF6B6B",
- "api_rph": 100,
- "api_rpm": 10,
- }
- # Create app
- app_service = AppService()
- app = app_service.create_app(tenant.id, app_args, account)
- # Setup current_user mock
- self._mock_current_user(mock_external_service_dependencies, account.id, tenant.id)
- return app, account
- def _mock_current_user(self, mock_external_service_dependencies, account_id, tenant_id):
- """
- Helper method to mock the current user for testing.
- """
- # mock_external_service_dependencies["current_user"].id = account_id
- # mock_external_service_dependencies["current_user"].current_tenant_id = tenant_id
- def _create_test_conversation(self, app, account, fake):
- """
- Helper method to create a test conversation with all required fields.
- """
- from extensions.ext_database import db
- from models.model import Conversation
- conversation = Conversation(
- app_id=app.id,
- app_model_config_id=None,
- model_provider=None,
- model_id="",
- override_model_configs=None,
- mode=app.mode,
- name=fake.sentence(),
- inputs={},
- introduction="",
- system_instruction="",
- system_instruction_tokens=0,
- status="normal",
- invoke_from="console",
- from_source="console",
- from_end_user_id=None,
- from_account_id=account.id,
- )
- db.session.add(conversation)
- db.session.flush()
- return conversation
- def _create_test_message(self, app, conversation, account, fake):
- """
- Helper method to create a test message with all required fields.
- """
- import json
- from extensions.ext_database import db
- from models.model import Message
- message = Message(
- app_id=app.id,
- model_provider=None,
- model_id="",
- override_model_configs=None,
- conversation_id=conversation.id,
- inputs={},
- query=fake.sentence(),
- message=json.dumps([{"role": "user", "text": fake.sentence()}]),
- message_tokens=0,
- message_unit_price=0,
- message_price_unit=0.001,
- answer=fake.text(max_nb_chars=200),
- answer_tokens=0,
- answer_unit_price=0,
- answer_price_unit=0.001,
- parent_message_id=None,
- provider_response_latency=0,
- total_price=0,
- currency="USD",
- invoke_from="console",
- from_source="console",
- from_end_user_id=None,
- from_account_id=account.id,
- )
- db.session.add(message)
- db.session.commit()
- return message
- def test_pagination_by_first_id_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful pagination by first ID.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and multiple messages
- conversation = self._create_test_conversation(app, account, fake)
- messages = []
- for i in range(5):
- message = self._create_test_message(app, conversation, account, fake)
- messages.append(message)
- # Test pagination by first ID
- result = MessageService.pagination_by_first_id(
- app_model=app,
- user=account,
- conversation_id=conversation.id,
- first_id=messages[2].id, # Use middle message as first_id
- limit=2,
- order="asc",
- )
- # Verify results
- assert result.limit == 2
- assert len(result.data) == 2
- # total 5, from the middle, no more
- assert result.has_more is False
- # Verify messages are in ascending order
- assert result.data[0].created_at <= result.data[1].created_at
- def test_pagination_by_first_id_no_user(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test pagination by first ID when no user is provided.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Test pagination with no user
- result = MessageService.pagination_by_first_id(
- app_model=app, user=None, conversation_id=fake.uuid4(), first_id=None, limit=10
- )
- # Verify empty result
- assert result.limit == 10
- assert len(result.data) == 0
- assert result.has_more is False
- def test_pagination_by_first_id_no_conversation_id(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test pagination by first ID when no conversation ID is provided.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Test pagination with no conversation ID
- result = MessageService.pagination_by_first_id(
- app_model=app, user=account, conversation_id="", first_id=None, limit=10
- )
- # Verify empty result
- assert result.limit == 10
- assert len(result.data) == 0
- assert result.has_more is False
- def test_pagination_by_first_id_invalid_first_id(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test pagination by first ID with invalid first_id.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- self._create_test_message(app, conversation, account, fake)
- # Test pagination with invalid first_id
- with pytest.raises(FirstMessageNotExistsError):
- MessageService.pagination_by_first_id(
- app_model=app,
- user=account,
- conversation_id=conversation.id,
- first_id=fake.uuid4(), # Non-existent message ID
- limit=10,
- )
- def test_pagination_by_last_id_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful pagination by last ID.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and multiple messages
- conversation = self._create_test_conversation(app, account, fake)
- messages = []
- for i in range(5):
- message = self._create_test_message(app, conversation, account, fake)
- messages.append(message)
- # Test pagination by last ID
- result = MessageService.pagination_by_last_id(
- app_model=app,
- user=account,
- last_id=messages[2].id, # Use middle message as last_id
- limit=2,
- conversation_id=conversation.id,
- )
- # Verify results
- assert result.limit == 2
- assert len(result.data) == 2
- # total 5, from the middle, no more
- assert result.has_more is False
- # Verify messages are in descending order
- assert result.data[0].created_at >= result.data[1].created_at
- def test_pagination_by_last_id_with_include_ids(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test pagination by last ID with include_ids filter.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and multiple messages
- conversation = self._create_test_conversation(app, account, fake)
- messages = []
- for i in range(5):
- message = self._create_test_message(app, conversation, account, fake)
- messages.append(message)
- # Test pagination with include_ids
- include_ids = [messages[0].id, messages[1].id, messages[2].id]
- result = MessageService.pagination_by_last_id(
- app_model=app, user=account, last_id=messages[1].id, limit=2, include_ids=include_ids
- )
- # Verify results
- assert result.limit == 2
- assert len(result.data) <= 2
- # Verify all returned messages are in include_ids
- for message in result.data:
- assert message.id in include_ids
- def test_pagination_by_last_id_no_user(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test pagination by last ID when no user is provided.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Test pagination with no user
- result = MessageService.pagination_by_last_id(app_model=app, user=None, last_id=None, limit=10)
- # Verify empty result
- assert result.limit == 10
- assert len(result.data) == 0
- assert result.has_more is False
- def test_pagination_by_last_id_invalid_last_id(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test pagination by last ID with invalid last_id.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- self._create_test_message(app, conversation, account, fake)
- # Test pagination with invalid last_id
- with pytest.raises(LastMessageNotExistsError):
- MessageService.pagination_by_last_id(
- app_model=app,
- user=account,
- last_id=fake.uuid4(), # Non-existent message ID
- limit=10,
- conversation_id=conversation.id,
- )
- def test_create_feedback_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful creation of feedback.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Create feedback
- rating = "like"
- content = fake.text(max_nb_chars=100)
- feedback = MessageService.create_feedback(
- app_model=app, message_id=message.id, user=account, rating=rating, content=content
- )
- # Verify feedback was created correctly
- assert feedback.app_id == app.id
- assert feedback.conversation_id == conversation.id
- assert feedback.message_id == message.id
- assert feedback.rating == rating
- assert feedback.content == content
- assert feedback.from_source == "admin"
- assert feedback.from_account_id == account.id
- assert feedback.from_end_user_id is None
- def test_create_feedback_no_user(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test creating feedback when no user is provided.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Test creating feedback with no user
- with pytest.raises(ValueError, match="user cannot be None"):
- MessageService.create_feedback(
- app_model=app, message_id=message.id, user=None, rating="like", content=fake.text(max_nb_chars=100)
- )
- def test_create_feedback_update_existing(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test updating existing feedback.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Create initial feedback
- initial_rating = "like"
- initial_content = fake.text(max_nb_chars=100)
- feedback = MessageService.create_feedback(
- app_model=app, message_id=message.id, user=account, rating=initial_rating, content=initial_content
- )
- # Update feedback
- updated_rating = "dislike"
- updated_content = fake.text(max_nb_chars=100)
- updated_feedback = MessageService.create_feedback(
- app_model=app, message_id=message.id, user=account, rating=updated_rating, content=updated_content
- )
- # Verify feedback was updated correctly
- assert updated_feedback.id == feedback.id
- assert updated_feedback.rating == updated_rating
- assert updated_feedback.content == updated_content
- assert updated_feedback.rating != initial_rating
- assert updated_feedback.content != initial_content
- def test_create_feedback_delete_existing(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test deleting existing feedback by setting rating to None.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Create initial feedback
- feedback = MessageService.create_feedback(
- app_model=app, message_id=message.id, user=account, rating="like", content=fake.text(max_nb_chars=100)
- )
- # Delete feedback by setting rating to None
- MessageService.create_feedback(app_model=app, message_id=message.id, user=account, rating=None, content=None)
- # Verify feedback was deleted
- from extensions.ext_database import db
- deleted_feedback = db.session.query(MessageFeedback).where(MessageFeedback.id == feedback.id).first()
- assert deleted_feedback is None
- def test_create_feedback_no_rating_when_not_exists(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test creating feedback with no rating when feedback doesn't exist.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Test creating feedback with no rating when no feedback exists
- with pytest.raises(ValueError, match="rating cannot be None when feedback not exists"):
- MessageService.create_feedback(
- app_model=app, message_id=message.id, user=account, rating=None, content=None
- )
- def test_get_all_messages_feedbacks_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful retrieval of all message feedbacks.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create multiple conversations and messages with feedbacks
- feedbacks = []
- for i in range(3):
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- feedback = MessageService.create_feedback(
- app_model=app,
- message_id=message.id,
- user=account,
- rating="like" if i % 2 == 0 else "dislike",
- content=f"Feedback {i}: {fake.text(max_nb_chars=50)}",
- )
- feedbacks.append(feedback)
- # Get all feedbacks
- result = MessageService.get_all_messages_feedbacks(app, page=1, limit=10)
- # Verify results
- assert len(result) == 3
- # Verify feedbacks are ordered by created_at desc
- for i in range(len(result) - 1):
- assert result[i]["created_at"] >= result[i + 1]["created_at"]
- def test_get_all_messages_feedbacks_pagination(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test pagination of message feedbacks.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create multiple conversations and messages with feedbacks
- for i in range(5):
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- MessageService.create_feedback(
- app_model=app, message_id=message.id, user=account, rating="like", content=f"Feedback {i}"
- )
- # Get feedbacks with pagination
- result_page_1 = MessageService.get_all_messages_feedbacks(app, page=1, limit=3)
- result_page_2 = MessageService.get_all_messages_feedbacks(app, page=2, limit=3)
- # Verify pagination results
- assert len(result_page_1) == 3
- assert len(result_page_2) == 2
- # Verify no overlap between pages
- page_1_ids = {feedback["id"] for feedback in result_page_1}
- page_2_ids = {feedback["id"] for feedback in result_page_2}
- assert len(page_1_ids.intersection(page_2_ids)) == 0
- def test_get_message_success(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test successful retrieval of message.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Get message
- retrieved_message = MessageService.get_message(app_model=app, user=account, message_id=message.id)
- # Verify message was retrieved correctly
- assert retrieved_message.id == message.id
- assert retrieved_message.app_id == app.id
- assert retrieved_message.conversation_id == conversation.id
- assert retrieved_message.from_source == "console"
- assert retrieved_message.from_account_id == account.id
- def test_get_message_not_exists(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test getting message that doesn't exist.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Test getting non-existent message
- with pytest.raises(MessageNotExistsError):
- MessageService.get_message(app_model=app, user=account, message_id=fake.uuid4())
- def test_get_message_wrong_user(self, db_session_with_containers, mock_external_service_dependencies):
- """
- Test getting message with wrong user (different account).
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Create another account
- from services.account_service import AccountService, TenantService
- other_account = AccountService.create_account(
- email=fake.email(),
- name=fake.name(),
- interface_language="en-US",
- password=fake.password(length=12),
- )
- TenantService.create_owner_tenant_if_not_exist(other_account, name=fake.company())
- # Test getting message with different user
- with pytest.raises(MessageNotExistsError):
- MessageService.get_message(app_model=app, user=other_account, message_id=message.id)
- def test_get_suggested_questions_after_answer_success(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test successful generation of suggested questions after answer.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Mock the LLMGenerator to return specific questions
- mock_questions = ["What is AI?", "How does machine learning work?", "Tell me about neural networks"]
- mock_external_service_dependencies[
- "llm_generator"
- ].generate_suggested_questions_after_answer.return_value = mock_questions
- # Get suggested questions
- from core.app.entities.app_invoke_entities import InvokeFrom
- result = MessageService.get_suggested_questions_after_answer(
- app_model=app, user=account, message_id=message.id, invoke_from=InvokeFrom.SERVICE_API
- )
- # Verify results
- assert result == mock_questions
- # Verify LLMGenerator was called
- mock_external_service_dependencies[
- "llm_generator"
- ].generate_suggested_questions_after_answer.assert_called_once()
- # Verify TraceQueueManager was called
- mock_external_service_dependencies["trace_manager_instance"].add_trace_task.assert_called_once()
- def test_get_suggested_questions_after_answer_no_user(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test getting suggested questions when no user is provided.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Test getting suggested questions with no user
- from core.app.entities.app_invoke_entities import InvokeFrom
- with pytest.raises(ValueError, match="user cannot be None"):
- MessageService.get_suggested_questions_after_answer(
- app_model=app, user=None, message_id=message.id, invoke_from=InvokeFrom.SERVICE_API
- )
- def test_get_suggested_questions_after_answer_disabled(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test getting suggested questions when feature is disabled.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Mock the feature to be disabled
- mock_external_service_dependencies[
- "app_config_manager"
- ].get_app_config.return_value.additional_features.suggested_questions_after_answer = False
- # Test getting suggested questions when feature is disabled
- from core.app.entities.app_invoke_entities import InvokeFrom
- with pytest.raises(SuggestedQuestionsAfterAnswerDisabledError):
- MessageService.get_suggested_questions_after_answer(
- app_model=app, user=account, message_id=message.id, invoke_from=InvokeFrom.SERVICE_API
- )
- def test_get_suggested_questions_after_answer_no_workflow(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test getting suggested questions when no workflow exists.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Mock no workflow
- mock_external_service_dependencies["workflow_service"].return_value.get_published_workflow.return_value = None
- # Get suggested questions (should return empty list)
- from core.app.entities.app_invoke_entities import InvokeFrom
- result = MessageService.get_suggested_questions_after_answer(
- app_model=app, user=account, message_id=message.id, invoke_from=InvokeFrom.SERVICE_API
- )
- # Verify empty result
- assert result == []
- def test_get_suggested_questions_after_answer_debugger_mode(
- self, db_session_with_containers, mock_external_service_dependencies
- ):
- """
- Test getting suggested questions in debugger mode.
- """
- fake = Faker()
- app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
- # Create a conversation and message
- conversation = self._create_test_conversation(app, account, fake)
- message = self._create_test_message(app, conversation, account, fake)
- # Mock questions
- mock_questions = ["Debug question 1", "Debug question 2"]
- mock_external_service_dependencies[
- "llm_generator"
- ].generate_suggested_questions_after_answer.return_value = mock_questions
- # Get suggested questions in debugger mode
- from core.app.entities.app_invoke_entities import InvokeFrom
- result = MessageService.get_suggested_questions_after_answer(
- app_model=app, user=account, message_id=message.id, invoke_from=InvokeFrom.DEBUGGER
- )
- # Verify results
- assert result == mock_questions
- # Verify draft workflow was used instead of published workflow
- mock_external_service_dependencies["workflow_service"].return_value.get_draft_workflow.assert_called_once_with(
- app_model=app
- )
- # Verify TraceQueueManager was called
- mock_external_service_dependencies["trace_manager_instance"].add_trace_task.assert_called_once()
|