Files
chatwoot/spec/services/crm/leadsquared/processor_service_spec.rb
2025-05-28 09:46:59 +05:30

234 lines
8.1 KiB
Ruby

require 'rails_helper'
RSpec.describe Crm::Leadsquared::ProcessorService do
let(:account) { create(:account) }
let(:hook) do
create(:integrations_hook, :leadsquared, account: account, settings: {
'access_key' => 'test_access_key',
'secret_key' => 'test_secret_key',
'endpoint_url' => 'https://api.leadsquared.com/v2',
'enable_transcript_activity' => true,
'enable_conversation_activity' => true,
'conversation_activity_code' => 1001,
'transcript_activity_code' => 1002
})
end
let(:contact) { create(:contact, account: account, email: 'test@example.com', phone_number: '+1234567890') }
let(:contact_with_social_profile) do
create(:contact, account: account, additional_attributes: { 'social_profiles' => { 'facebook' => 'chatwootapp' } })
end
let(:blank_contact) { create(:contact, account: account, email: '', phone_number: '') }
let(:conversation) { create(:conversation, account: account, contact: contact) }
let(:service) { described_class.new(hook) }
let(:lead_client) { instance_double(Crm::Leadsquared::Api::LeadClient) }
let(:activity_client) { instance_double(Crm::Leadsquared::Api::ActivityClient) }
let(:lead_finder) { instance_double(Crm::Leadsquared::LeadFinderService) }
before do
account.enable_features('crm_integration')
allow(Crm::Leadsquared::Api::LeadClient).to receive(:new)
.with('test_access_key', 'test_secret_key', 'https://api.leadsquared.com/v2')
.and_return(lead_client)
allow(Crm::Leadsquared::Api::ActivityClient).to receive(:new)
.with('test_access_key', 'test_secret_key', 'https://api.leadsquared.com/v2')
.and_return(activity_client)
allow(Crm::Leadsquared::LeadFinderService).to receive(:new)
.with(lead_client)
.and_return(lead_finder)
end
describe '.crm_name' do
it 'returns leadsquared' do
expect(described_class.crm_name).to eq('leadsquared')
end
end
describe '#handle_contact' do
context 'when contact is valid' do
before do
allow(service).to receive(:identifiable_contact?).and_return(true)
end
context 'when contact has no stored lead ID' do
before do
contact.update(additional_attributes: { 'external' => nil })
contact.reload
allow(lead_client).to receive(:create_or_update_lead)
.with(any_args)
.and_return('new_lead_id')
end
it 'creates a new lead and stores the ID' do
service.handle_contact(contact)
expect(lead_client).to have_received(:create_or_update_lead).with(any_args)
expect(contact.reload.additional_attributes['external']['leadsquared_id']).to eq('new_lead_id')
end
end
context 'when contact has existing lead ID' do
before do
contact.additional_attributes = { 'external' => { 'leadsquared_id' => 'existing_lead_id' } }
contact.save!
allow(lead_client).to receive(:update_lead)
.with(any_args)
.and_return(nil) # The update method doesn't need to return anything
end
it 'updates the lead using existing ID' do
service.handle_contact(contact)
expect(lead_client).to have_received(:update_lead).with(any_args)
end
end
context 'when API call raises an error' do
before do
allow(lead_client).to receive(:create_or_update_lead)
.with(any_args)
.and_raise(Crm::Leadsquared::Api::BaseClient::ApiError.new('API Error'))
allow(Rails.logger).to receive(:error)
end
it 'catches and logs the error' do
service.handle_contact(contact)
expect(Rails.logger).to have_received(:error).with(/LeadSquared API error/)
end
end
end
context 'when contact is invalid' do
before do
allow(service).to receive(:identifiable_contact?).and_return(false)
allow(lead_client).to receive(:create_or_update_lead)
end
it 'returns without making API calls' do
service.handle_contact(blank_contact)
expect(lead_client).not_to have_received(:create_or_update_lead)
end
end
end
describe '#handle_conversation_created' do
let(:activity_note) { 'New conversation started' }
before do
allow(Crm::Leadsquared::Mappers::ConversationMapper).to receive(:map_conversation_activity)
.with(hook, conversation)
.and_return(activity_note)
end
context 'when conversation activities are enabled' do
before do
service.instance_variable_set(:@allow_conversation, true)
end
context 'when lead_id is found' do
before do
allow(lead_finder).to receive(:find_or_create)
.with(contact)
.and_return('test_lead_id')
allow(activity_client).to receive(:post_activity)
.with('test_lead_id', 1001, activity_note)
.and_return('test_activity_id')
end
it 'creates the activity and stores metadata' do
service.handle_conversation_created(conversation)
expect(conversation.reload.additional_attributes['leadsquared']['created_activity_id']).to eq('test_activity_id')
end
end
context 'when post_activity raises an error' do
before do
allow(lead_finder).to receive(:find_or_create)
.with(contact)
.and_return('test_lead_id')
allow(activity_client).to receive(:post_activity)
.with('test_lead_id', 1001, activity_note)
.and_raise(StandardError.new('Activity error'))
allow(Rails.logger).to receive(:error)
end
it 'logs the error' do
service.handle_conversation_created(conversation)
expect(Rails.logger).to have_received(:error).with(/Error creating conversation activity/)
end
end
end
context 'when conversation activities are disabled' do
before do
service.instance_variable_set(:@allow_conversation, false)
allow(activity_client).to receive(:post_activity)
end
it 'does not create an activity' do
service.handle_conversation_created(conversation)
expect(activity_client).not_to have_received(:post_activity)
end
end
end
describe '#handle_conversation_resolved' do
let(:activity_note) { 'Conversation transcript' }
before do
allow(Crm::Leadsquared::Mappers::ConversationMapper).to receive(:map_transcript_activity)
.with(hook, conversation)
.and_return(activity_note)
end
context 'when transcript activities are enabled and conversation is resolved' do
before do
service.instance_variable_set(:@allow_transcript, true)
conversation.update!(status: 'resolved')
allow(lead_finder).to receive(:find_or_create)
.with(contact)
.and_return('test_lead_id')
allow(activity_client).to receive(:post_activity)
.with('test_lead_id', 1002, activity_note)
.and_return('test_activity_id')
end
it 'creates the transcript activity and stores metadata' do
service.handle_conversation_resolved(conversation)
expect(conversation.reload.additional_attributes['leadsquared']['transcript_activity_id']).to eq('test_activity_id')
end
end
context 'when conversation is not resolved' do
before do
service.instance_variable_set(:@allow_transcript, true)
conversation.update!(status: 'open')
allow(activity_client).to receive(:post_activity)
end
it 'does not create an activity' do
service.handle_conversation_resolved(conversation)
expect(activity_client).not_to have_received(:post_activity)
end
end
context 'when transcript activities are disabled' do
before do
service.instance_variable_set(:@allow_transcript, false)
conversation.update!(status: 'resolved')
allow(activity_client).to receive(:post_activity)
end
it 'does not create an activity' do
service.handle_conversation_resolved(conversation)
expect(activity_client).not_to have_received(:post_activity)
end
end
end
end