528 lines
27 KiB
Ruby
528 lines
27 KiB
Ruby
require 'rails_helper'
|
|
|
|
describe Whatsapp::IncomingMessageService do
|
|
describe '#perform' do
|
|
before do
|
|
stub_request(:post, 'https://waba.360dialog.io/v1/configs/webhook')
|
|
end
|
|
|
|
after do
|
|
# The atomic dedup lock lives in Redis and is not rolled back by
|
|
# transactional fixtures. Clean up any keys created during the test.
|
|
Redis::Alfred.scan_each(match: 'MESSAGE_SOURCE_KEY::*') do |key|
|
|
Redis::Alfred.delete(key)
|
|
end
|
|
end
|
|
|
|
let!(:whatsapp_channel) { create(:channel_whatsapp, sync_templates: false) }
|
|
let(:wa_id) { '2423423243' }
|
|
let!(:params) do
|
|
{
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => wa_id }],
|
|
'messages' => [{ 'from' => wa_id, 'id' => 'SDFADSf23sfasdafasdfa', 'text' => { 'body' => 'Test' },
|
|
'timestamp' => '1633034394', 'type' => 'text' }]
|
|
}.with_indifferent_access
|
|
end
|
|
|
|
context 'when valid text message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
|
end
|
|
|
|
it 'appends to last conversation when if conversation already exists' do
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
|
|
2.times.each { create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox) }
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# no new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(3)
|
|
# message appended to the last conversation
|
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
end
|
|
|
|
it 'reopen last conversation if last conversation is resolved and lock to single conversation is enabled' do
|
|
whatsapp_channel.inbox.update(lock_to_single_conversation: true)
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
last_conversation.update(status: 'resolved')
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# no new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
|
# message appended to the last conversation
|
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
expect(last_conversation.reload.status).to eq('open')
|
|
end
|
|
|
|
it 'creates a new conversation if last conversation is resolved and lock to single conversation is disabled' do
|
|
whatsapp_channel.inbox.update(lock_to_single_conversation: false)
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
last_conversation.update(status: 'resolved')
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(2)
|
|
expect(contact_inbox.conversations.last.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
end
|
|
|
|
it 'will not create a new conversation if last conversation is not resolved and lock to single conversation is disabled' do
|
|
whatsapp_channel.inbox.update(lock_to_single_conversation: false)
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: params[:messages].first[:from])
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
last_conversation.update(status: Conversation.statuses.except('resolved').keys.sample)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
|
expect(contact_inbox.conversations.last.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
end
|
|
|
|
it 'will not create duplicate messages when same message is received' do
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.messages.count).to eq(1)
|
|
|
|
# this shouldn't create a duplicate message
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.messages.count).to eq(1)
|
|
end
|
|
end
|
|
|
|
context 'when unsupported message types' do
|
|
it 'ignores type ephemeral and does not create ghost conversation' do
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
|
|
'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa', 'text' => { 'body' => 'Test' },
|
|
'timestamp' => '1633034394', 'type' => 'ephemeral' }]
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(0)
|
|
expect(Contact.count).to eq(0)
|
|
expect(whatsapp_channel.inbox.messages.count).to eq(0)
|
|
end
|
|
|
|
it 'ignores type unsupported and does not create ghost conversation' do
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
|
|
'messages' => [{
|
|
'errors' => [{ 'code': 131_051, 'title': 'Message type is currently not supported.' }],
|
|
:from => '2423423243', :id => 'wamid.SDFADSf23sfasdafasdfa',
|
|
:timestamp => '1667047370', :type => 'unsupported'
|
|
}]
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(0)
|
|
expect(Contact.count).to eq(0)
|
|
expect(whatsapp_channel.inbox.messages.count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context 'when valid status params' do
|
|
let(:from) { '2423423243' }
|
|
let(:contact_inbox) { create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: from) }
|
|
let(:params) do
|
|
{
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => from }],
|
|
'messages' => [{ 'from' => from, 'id' => from, 'text' => { 'body' => 'Test' },
|
|
'timestamp' => '1633034394', 'type' => 'text' }]
|
|
}.with_indifferent_access
|
|
end
|
|
|
|
before do
|
|
create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
end
|
|
|
|
it 'update status message to read' do
|
|
status_params = {
|
|
'statuses' => [{ 'recipient_id' => from, 'id' => from, 'status' => 'read' }]
|
|
}.with_indifferent_access
|
|
message = Message.find_by!(source_id: from)
|
|
expect(message.status).to eq('sent')
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: status_params).perform
|
|
expect(message.reload.status).to eq('read')
|
|
end
|
|
|
|
it 'update status message to failed' do
|
|
status_params = {
|
|
'statuses' => [{ 'recipient_id' => from, 'id' => from, 'status' => 'failed',
|
|
'errors' => [{ 'code': 123, 'title': 'abc' }] }]
|
|
}.with_indifferent_access
|
|
|
|
message = Message.find_by!(source_id: from)
|
|
expect(message.status).to eq('sent')
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: status_params).perform
|
|
expect(message.reload.status).to eq('failed')
|
|
expect(message.external_error).to eq('123: abc')
|
|
end
|
|
|
|
it 'will not throw error if unsupported status' do
|
|
status_params = {
|
|
'statuses' => [{ 'recipient_id' => from, 'id' => from, 'status' => 'deleted',
|
|
'errors' => [{ 'code': 123, 'title': 'abc' }] }]
|
|
}.with_indifferent_access
|
|
|
|
message = Message.find_by!(source_id: from)
|
|
expect(message.status).to eq('sent')
|
|
expect { described_class.new(inbox: whatsapp_channel.inbox, params: status_params).perform }.not_to raise_error
|
|
end
|
|
end
|
|
|
|
context 'when valid interactive message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
|
|
'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa',
|
|
:interactive => {
|
|
'button_reply': {
|
|
'id': '1',
|
|
'title': 'First Button'
|
|
},
|
|
'type': 'button_reply'
|
|
},
|
|
'timestamp' => '1633034394', 'type' => 'interactive' }]
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('First Button')
|
|
end
|
|
end
|
|
|
|
# ref: https://github.com/chatwoot/chatwoot/issues/3795#issuecomment-1018057318
|
|
context 'when valid template button message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
|
|
'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa',
|
|
'button' => {
|
|
'text' => 'Yes this is a button'
|
|
},
|
|
'timestamp' => '1633034394', 'type' => 'button' }]
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Yes this is a button')
|
|
end
|
|
end
|
|
|
|
context 'when valid attachment message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
stub_request(:get, whatsapp_channel.media_url('b1c68f38-8734-4ad3-b4a1-ef0c10d683')).to_return(
|
|
status: 200,
|
|
body: File.read('spec/assets/sample.png'),
|
|
headers: {}
|
|
)
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
|
|
'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa',
|
|
'image' => { 'id' => 'b1c68f38-8734-4ad3-b4a1-ef0c10d683',
|
|
'mime_type' => 'image/jpeg',
|
|
'sha256' => '29ed500fa64eb55fc19dc4124acb300e5dcca0f822a301ae99944db',
|
|
'caption' => 'Check out my product!' },
|
|
'timestamp' => '1633034394', 'type' => 'image' }]
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Check out my product!')
|
|
expect(whatsapp_channel.inbox.messages.first.attachments.present?).to be true
|
|
end
|
|
end
|
|
|
|
context 'when valid location message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
|
|
'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa',
|
|
'location' => { 'id' => 'b1c68f38-8734-4ad3-b4a1-ef0c10d683',
|
|
:address => 'San Francisco, CA, USA',
|
|
:latitude => 37.7893768,
|
|
:longitude => -122.3895553,
|
|
:name => 'Bay Bridge',
|
|
:url => 'http://location_url.test' },
|
|
'timestamp' => '1633034394', 'type' => 'location' }]
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
location_attachment = whatsapp_channel.inbox.messages.first.attachments.first
|
|
expect(location_attachment.file_type).to eq('location')
|
|
expect(location_attachment.fallback_title).to eq('Bay Bridge, San Francisco, CA, USA')
|
|
expect(location_attachment.coordinates_lat).to eq(37.7893768)
|
|
expect(location_attachment.coordinates_long).to eq(-122.3895553)
|
|
expect(location_attachment.external_url).to eq('http://location_url.test')
|
|
end
|
|
end
|
|
|
|
context 'when valid contact message params' do
|
|
it 'creates appropriate message and attachments' do
|
|
params = { 'contacts' => [{ 'profile' => { 'name' => 'Kedar' }, 'wa_id' => '919746334593' }],
|
|
'messages' => [{ 'from' => '919446284490',
|
|
'id' => 'wamid.SDFADSf23sfasdafasdfa',
|
|
'timestamp' => '1675823265',
|
|
'type' => 'contacts',
|
|
'contacts' => [
|
|
{
|
|
'name' => { 'formatted_name' => 'Apple Inc.' },
|
|
'phones' => [{ 'phone' => '+911800', 'type' => 'MAIN' }]
|
|
},
|
|
{ 'name' => { 'first_name' => 'Chatwoot', 'formatted_name' => 'Chatwoot' },
|
|
'phones' => [{ 'phone' => '+1 (415) 341-8386' }] }
|
|
] }] }.with_indifferent_access
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(Contact.all.first.name).to eq('Kedar')
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
|
|
m1 = whatsapp_channel.inbox.messages.first
|
|
expect(m1.content).to eq('Apple Inc.')
|
|
expect(m1.attachments.first.fallback_title).to eq('+911800')
|
|
expect(m1.attachments.first.meta).to eq({})
|
|
|
|
m2 = whatsapp_channel.inbox.messages.last
|
|
expect(m2.content).to eq('Chatwoot')
|
|
expect(m2.attachments.first.meta).to eq({ 'firstName' => 'Chatwoot' })
|
|
end
|
|
end
|
|
|
|
# ref: https://github.com/chatwoot/chatwoot/issues/5840
|
|
describe 'When the incoming waid is a brazilian number in new format with 9 included' do
|
|
let(:wa_id) { '5541988887777' }
|
|
|
|
it 'creates appropriate conversations, message and contacts if contact does not exit' do
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
|
end
|
|
|
|
it 'appends to existing contact if contact inbox exists' do
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# no new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
|
# message appended to the last conversation
|
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
end
|
|
end
|
|
|
|
describe 'When incoming waid is a brazilian number in old format without the 9 included' do
|
|
let(:wa_id) { '554188887777' }
|
|
|
|
context 'when a contact inbox exists in the old format without 9 included' do
|
|
it 'appends to existing contact' do
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# no new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
|
# message appended to the last conversation
|
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
end
|
|
end
|
|
|
|
context 'when a contact inbox exists in the new format with 9 included' do
|
|
it 'appends to existing contact' do
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: '5541988887777')
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# no new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
|
# message appended to the last conversation
|
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
end
|
|
end
|
|
|
|
context 'when a contact inbox does not exist in the new format with 9 included' do
|
|
it 'creates contact inbox with the incoming waid' do
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'When the incoming waid is an Argentine number with 9 after country code' do
|
|
let(:wa_id) { '5491123456789' }
|
|
|
|
it 'creates appropriate conversations, message and contacts if contact does not exist' do
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
|
end
|
|
|
|
it 'appends to existing contact if contact inbox exists with normalized format' do
|
|
# Normalized format removes the 9 after country code
|
|
normalized_wa_id = '541123456789'
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: normalized_wa_id)
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# no new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
|
# message appended to the last conversation
|
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
# should use the normalized wa_id from existing contact
|
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(normalized_wa_id)
|
|
end
|
|
end
|
|
|
|
describe 'When incoming waid is an Argentine number without 9 after country code' do
|
|
let(:wa_id) { '541123456789' }
|
|
|
|
context 'when a contact inbox exists with the same format' do
|
|
it 'appends to existing contact' do
|
|
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
|
|
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
# no new conversation should be created
|
|
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
|
|
# message appended to the last conversation
|
|
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
|
|
end
|
|
end
|
|
|
|
context 'when a contact inbox does not exist' do
|
|
it 'creates contact inbox with the incoming waid' do
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(Contact.all.first.name).to eq('Sojan Jose')
|
|
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
|
|
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'when another worker already holds the dedup lock' do
|
|
it 'skips message creation' do
|
|
params = { 'contacts' => [{ 'profile' => { 'name' => 'Kedar' }, 'wa_id' => '919746334593' }],
|
|
'messages' => [{ 'from' => '919446284490',
|
|
'id' => 'wamid.SDFADSf23sfasdafasdfa',
|
|
'timestamp' => '1675823265',
|
|
'type' => 'contacts',
|
|
'contacts' => [
|
|
{
|
|
'name' => { 'formatted_name' => 'Apple Inc.' },
|
|
'phones' => [{ 'phone' => '+911800', 'type' => 'MAIN' }]
|
|
},
|
|
{ 'name' => { 'first_name' => 'Chatwoot', 'formatted_name' => 'Chatwoot' },
|
|
'phones' => [{ 'phone' => '+1 (415) 341-8386' }] }
|
|
] }] }.with_indifferent_access
|
|
|
|
# Simulate another worker holding the lock
|
|
lock = Whatsapp::MessageDedupLock.new('wamid.SDFADSf23sfasdafasdfa')
|
|
expect(lock.acquire!).to be_truthy
|
|
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
expect(whatsapp_channel.inbox.messages.count).to eq(0)
|
|
ensure
|
|
key = format(Redis::RedisKeys::MESSAGE_SOURCE_KEY, id: 'wamid.SDFADSf23sfasdafasdfa')
|
|
Redis::Alfred.delete(key)
|
|
end
|
|
end
|
|
|
|
context 'when profile name is available for contact updates' do
|
|
let(:wa_id) { '1234567890' }
|
|
let(:phone_number) { "+#{wa_id}" }
|
|
|
|
it 'updates existing contact name when current name matches phone number' do
|
|
# Create contact with phone number as name
|
|
existing_contact = create(:contact,
|
|
account: whatsapp_channel.inbox.account,
|
|
name: phone_number,
|
|
phone_number: phone_number)
|
|
create(:contact_inbox,
|
|
contact: existing_contact,
|
|
inbox: whatsapp_channel.inbox,
|
|
source_id: wa_id)
|
|
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Jane Smith' }, 'wa_id' => wa_id }],
|
|
'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
|
|
'timestamp' => '1633034394', 'type' => 'text' }]
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
existing_contact.reload
|
|
expect(existing_contact.name).to eq('Jane Smith')
|
|
end
|
|
|
|
it 'does not update contact name when current name is different from phone number' do
|
|
# Create contact with human name
|
|
existing_contact = create(:contact,
|
|
account: whatsapp_channel.inbox.account,
|
|
name: 'John Doe',
|
|
phone_number: phone_number)
|
|
create(:contact_inbox,
|
|
contact: existing_contact,
|
|
inbox: whatsapp_channel.inbox,
|
|
source_id: wa_id)
|
|
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Jane Smith' }, 'wa_id' => wa_id }],
|
|
'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
|
|
'timestamp' => '1633034394', 'type' => 'text' }]
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
existing_contact.reload
|
|
expect(existing_contact.name).to eq('John Doe') # Should not change
|
|
end
|
|
|
|
it 'updates contact name when current name matches formatted phone number' do
|
|
formatted_number = TelephoneNumber.parse(phone_number).international_number
|
|
|
|
# Create contact with formatted phone number as name
|
|
existing_contact = create(:contact,
|
|
account: whatsapp_channel.inbox.account,
|
|
name: formatted_number,
|
|
phone_number: phone_number)
|
|
create(:contact_inbox,
|
|
contact: existing_contact,
|
|
inbox: whatsapp_channel.inbox,
|
|
source_id: wa_id)
|
|
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => 'Alice Johnson' }, 'wa_id' => wa_id }],
|
|
'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
|
|
'timestamp' => '1633034394', 'type' => 'text' }]
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
existing_contact.reload
|
|
expect(existing_contact.name).to eq('Alice Johnson')
|
|
end
|
|
|
|
it 'does not update when profile name is blank' do
|
|
# Create contact with phone number as name
|
|
existing_contact = create(:contact,
|
|
account: whatsapp_channel.inbox.account,
|
|
name: phone_number,
|
|
phone_number: phone_number)
|
|
create(:contact_inbox,
|
|
contact: existing_contact,
|
|
inbox: whatsapp_channel.inbox,
|
|
source_id: wa_id)
|
|
|
|
params = {
|
|
'contacts' => [{ 'profile' => { 'name' => '' }, 'wa_id' => wa_id }],
|
|
'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
|
|
'timestamp' => '1633034394', 'type' => 'text' }]
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
|
|
existing_contact.reload
|
|
expect(existing_contact.name).to eq(phone_number) # Should not change
|
|
end
|
|
end
|
|
end
|
|
end
|