Chatwoot/spec/services/whatsapp/incoming_message_service_spec.rb
Clairton Rodrigo Heinzen edcbd53425
feat: Read/Delivery status for Whatsapp Cloud API (#5157)
Process field statuses received in webhook WhatsApp cloud API

ref: #1021

Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: Nithin David <1277421+nithindavid@users.noreply.github.com>
2022-11-29 15:51:37 +03:00

201 lines
10 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
let!(:whatsapp_channel) { create(:channel_whatsapp, sync_templates: false) }
context 'when valid text 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', 'text' => { 'body' => 'Test' },
'timestamp' => '1633034394', 'type' => 'text' }]
}.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('Test')
end
it 'appends to last conversation when if conversation already exisits' do
params = {
'contacts' => [{ 'profile' => { 'name' => 'Sojan Jose' }, 'wa_id' => '2423423243' }],
'messages' => [{ 'from' => '2423423243', 'id' => 'SDFADSf23sfasdafasdfa', 'text' => { 'body' => 'Test' },
'timestamp' => '1633034394', 'type' => 'text' }]
}.with_indifferent_access
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
end
context 'when unsupported message types' do
it 'ignores type ephemeral' 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).not_to eq(0)
expect(Contact.all.first.name).to eq('Sojan Jose')
expect(whatsapp_channel.inbox.messages.count).to eq(0)
end
it 'ignores type unsupported' 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).not_to eq(0)
expect(Contact.all.first.name).to eq('Sojan Jose')
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
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
end
end