diff --git a/spec/lib/captain/reply_suggestion_service_spec.rb b/spec/lib/captain/reply_suggestion_service_spec.rb new file mode 100644 index 000000000..c5ce45ea2 --- /dev/null +++ b/spec/lib/captain/reply_suggestion_service_spec.rb @@ -0,0 +1,75 @@ +require 'rails_helper' + +RSpec.describe Captain::ReplySuggestionService do + let(:account) { create(:account) } + let(:inbox) { create(:inbox, account: account) } + let(:conversation) { create(:conversation, account: account, inbox: inbox) } + let(:event) do + { + 'name' => 'reply_suggestion', + 'data' => { + 'conversation_display_id' => conversation.display_id + } + } + end + let(:service) { described_class.new(account: account, event: event) } + let(:mock_chat) { instance_double(RubyLLM::Chat) } + let(:mock_context) { instance_double(RubyLLM::Context, chat: mock_chat) } + let(:mock_response) { instance_double(RubyLLM::Message, content: 'Suggested reply', input_tokens: 100, output_tokens: 50) } + + before do + create(:installation_config, name: 'CAPTAIN_OPEN_AI_API_KEY', value: 'test-key') + allow(Llm::Config).to receive(:with_api_key).and_yield(mock_context) + allow(mock_chat).to receive(:with_instructions) + allow(mock_chat).to receive(:add_message) + allow(mock_chat).to receive(:ask).and_return(mock_response) + end + + describe '#reply_suggestion_message' do + let(:message1) { create(:message, conversation: conversation, message_type: :incoming, content: 'Hello') } + let(:message2) { create(:message, conversation: conversation, message_type: :outgoing, content: 'Hi there') } + + before do + message1 + message2 + end + + it 'uses conversation_messages to build message history' do + expect(service).to receive(:conversation_messages).and_call_original + service.reply_suggestion_message + end + + it 'concatenates system prompt with conversation history' do + allow(service).to receive(:prompt_from_file).with('reply').and_return('Help with reply') + + expect(service).to receive(:make_api_call) do |args| + expected_messages = [ + { role: 'system', content: 'Help with reply' }, + { role: 'user', content: 'Hello' }, + { role: 'assistant', content: 'Hi there' } + ] + + expect(args[:messages]).to eq(expected_messages) + { message: 'Suggested reply' } + end + + service.reply_suggestion_message + end + + it 'passes correct model to API' do + expect(service).to receive(:make_api_call).with( + hash_including(model: Captain::BaseEditorService::GPT_MODEL) + ).and_call_original + + service.reply_suggestion_message + end + + it 'returns formatted response' do + result = service.reply_suggestion_message + + expect(result[:message]).to eq('Suggested reply') + expect(result[:usage]['prompt_tokens']).to eq(100) + expect(result[:usage]['completion_tokens']).to eq(50) + end + end +end