fix: mark message read edge case (#46)
* feat: enhance message_content_attributes to handle reaction messages * fix: update external_created_at to use raw message timestamp directly * fix: update readableTime to use externalCreatedAt if available * feat: enhance timestamp formatting with localization support for pt-BR * feat: add note to message_content_attributes about external_created_at timestamp * fix: add missing newline at end of conversation.json files * test: add additional cases for messageTimestamp formatting * chore: remove outdated note about external_created_at in message_content_attributes * refactor: remove out of scope task changes * feat: add test for setting external_created_at in content_attributes on new message * fix: use last_seen_at message query conditions only if present * test: add SQL execution tests for messages_read with last_seen_at conditions * fix: ensure SQL notifications are unsubscribed after message read events * refactor: streamline message query in messages_read method * test: update messages_read specs to test expected behavior * refactor: simplify readableTime computation by removing unnecessary externalCreatedAt check * fix: update readableTime computation to use externalCreatedAt if available * test: enhance messages_read specs to use a consistent event object * test: refactor spec for creating message with external_created_at in messages.upsert event * Refactor incoming message specs for clarity and consistency - Consolidated raw_message and params definitions using let blocks for better readability. - Updated tests to directly manipulate raw_message and params within individual examples. - Ensured consistent naming and structure across different message types. - Improved assertions to reflect changes in message attributes and expectations. * refactor: streamline messages.update event handling and improve test clarity * test: refactor messages.upsert event specs to use a consistent timestamp * test: enhance reaction message handling in incoming_message_baileys_service_spec
This commit is contained in:
parent
3e5a42e5bc
commit
a760442010
@ -32,7 +32,10 @@ const {
|
||||
} = useMessageContext();
|
||||
|
||||
const readableTime = computed(() =>
|
||||
messageTimestamp(createdAt.value, 'LLL d, h:mm a')
|
||||
messageTimestamp(
|
||||
contentAttributes?.value?.externalCreatedAt ?? createdAt.value,
|
||||
'LLL d, h:mm a'
|
||||
)
|
||||
);
|
||||
|
||||
const showStatusIndicator = computed(() => {
|
||||
|
||||
@ -28,9 +28,9 @@ class ChannelListener < BaseListener
|
||||
channel = conversation.inbox.channel
|
||||
return unless channel.respond_to?(:send_read_messages)
|
||||
|
||||
messages = conversation.messages.where(message_type: :incoming)
|
||||
.where('updated_at > ?', last_seen_at)
|
||||
.where.not(status: :read)
|
||||
messages = conversation.messages.where(message_type: :incoming).where.not(status: :read)
|
||||
|
||||
messages = messages.where('updated_at > ?', last_seen_at) if last_seen_at.present?
|
||||
|
||||
channel.send_read_messages(messages, conversation: conversation) if messages.any?
|
||||
end
|
||||
|
||||
@ -171,16 +171,17 @@ class Whatsapp::IncomingMessageBaileysService < Whatsapp::IncomingMessageBaseSer
|
||||
end
|
||||
|
||||
def message_content_attributes
|
||||
content_attributes = {
|
||||
external_created_at: @raw_message[:messageTimestamp]
|
||||
}
|
||||
if message_type == 'reaction'
|
||||
{
|
||||
in_reply_to_external_id: @raw_message.dig(:message, :reactionMessage, :key, :id),
|
||||
is_reaction: true
|
||||
}
|
||||
content_attributes[:in_reply_to_external_id] = @raw_message.dig(:message, :reactionMessage, :key, :id)
|
||||
content_attributes[:is_reaction] = true
|
||||
elsif message_type == 'unsupported'
|
||||
{
|
||||
is_unsupported: true
|
||||
}
|
||||
content_attributes[:is_unsupported] = true
|
||||
end
|
||||
|
||||
content_attributes
|
||||
end
|
||||
|
||||
def incoming?
|
||||
|
||||
@ -95,12 +95,13 @@ describe ChannelListener do
|
||||
let(:channel) { create(:channel_whatsapp, sync_templates: false, validate_provider_config: false) }
|
||||
let(:conversation) { create(:conversation, inbox: create(:inbox, channel: channel)) }
|
||||
let(:last_seen_at) { 1.day.ago }
|
||||
let(:event) { Events::Base.new(Events::Types::MESSAGES_READ, Time.zone.now, conversation: conversation, last_seen_at: last_seen_at) }
|
||||
|
||||
it 'sends read messages to the channel' do
|
||||
sent_message = create(:message, conversation: conversation, message_type: :incoming, status: :sent)
|
||||
create(:message, conversation: conversation, message_type: :incoming, status: :read)
|
||||
sent_message = create(:message, conversation: conversation, message_type: :incoming, status: :sent)
|
||||
|
||||
allow(channel).to receive(:send_read_messages).with([sent_message], conversation: conversation)
|
||||
event = Events::Base.new(Events::Types::MESSAGES_READ, Time.zone.now, conversation: conversation, last_seen_at: last_seen_at)
|
||||
|
||||
listener.messages_read(event)
|
||||
|
||||
@ -111,9 +112,41 @@ describe ChannelListener do
|
||||
create(:channel_api, inbox: conversation.inbox)
|
||||
|
||||
expect do
|
||||
listener.messages_read(Events::Base.new(Events::Types::MESSAGES_READ, Time.zone.now, conversation: conversation, last_seen_at: last_seen_at))
|
||||
listener.messages_read(event)
|
||||
end.not_to raise_error
|
||||
end
|
||||
|
||||
it 'skips the event if there are no unread messages' do
|
||||
create(:message, conversation: conversation, message_type: :incoming, status: :read)
|
||||
|
||||
allow(channel).to receive(:send_read_messages)
|
||||
|
||||
listener.messages_read(event)
|
||||
|
||||
expect(channel).not_to have_received(:send_read_messages)
|
||||
end
|
||||
|
||||
it 'filters messages ignoring last_seen_at' do
|
||||
old_message = create(:message, conversation: conversation, message_type: :incoming, status: :sent, updated_at: last_seen_at - 1.day)
|
||||
recent_message = create(:message, conversation: conversation, message_type: :incoming, status: :sent, updated_at: Time.zone.now)
|
||||
|
||||
allow(channel).to receive(:send_read_messages).with([old_message, recent_message], conversation: conversation)
|
||||
|
||||
listener.messages_read(Events::Base.new(Events::Types::MESSAGES_READ, Time.zone.now, conversation: conversation, last_seen_at: nil))
|
||||
|
||||
expect(channel).to have_received(:send_read_messages)
|
||||
end
|
||||
|
||||
it 'filters messages based on last_seen_at' do
|
||||
create(:message, conversation: conversation, message_type: :incoming, status: :sent, updated_at: last_seen_at - 1.day)
|
||||
recent_message = create(:message, conversation: conversation, message_type: :incoming, status: :sent, updated_at: Time.zone.now)
|
||||
|
||||
allow(channel).to receive(:send_read_messages).with([recent_message], conversation: conversation)
|
||||
|
||||
listener.messages_read(event)
|
||||
|
||||
expect(channel).to have_received(:send_read_messages)
|
||||
end
|
||||
end
|
||||
|
||||
def build_typing_event(event_name, conversation:, is_private: false)
|
||||
|
||||
@ -145,79 +145,65 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when processing messages.upsert event' do
|
||||
context 'when message type is unsupported' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { unsupported: 'message' },
|
||||
pushName: 'John Doe'
|
||||
let(:timestamp) { Time.current.to_i }
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
pushName: 'John Doe',
|
||||
messageTimestamp: timestamp,
|
||||
message: { conversation: 'Hello from Baileys' }
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
}
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates message with external_created_at' do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
message = conversation.messages.last
|
||||
|
||||
expect(message).to be_present
|
||||
expect(message.content_attributes[:external_created_at]).to eq(timestamp)
|
||||
end
|
||||
|
||||
context 'when message type is unsupported' do
|
||||
it 'creates message with is_unsupported' do
|
||||
raw_message[:message] = { unsupported: 'message' }
|
||||
|
||||
it 'creates an unsupported message' do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
message = conversation.messages.last
|
||||
|
||||
expect(message).to be_present
|
||||
expect(message.is_unsupported).to be(true)
|
||||
expect(message.content_attributes[:is_unsupported]).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is protocol message' do
|
||||
let(:raw_message) do
|
||||
{ key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { protocolMessage: { type: 1 } },
|
||||
pushName: 'John Doe' }
|
||||
end
|
||||
let(:params) do
|
||||
{ webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
} }
|
||||
end
|
||||
|
||||
it 'does not create contact inbox nor message' do
|
||||
raw_message[:message] = { protocolMessage: { type: 1 } }
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
expect(inbox.contact_inboxes.count).to be(0)
|
||||
expect(inbox.messages.count).to be(0)
|
||||
expect(inbox.messages).to be_empty
|
||||
expect(inbox.contact_inboxes).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is not from a user' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: 'status@broadcast', participant: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { extendedTextMessage: { text: 'message' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'does not create a conversation' do
|
||||
raw_message[:key][:remoteJid] = 'status@broadcast'
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
expect(inbox.conversations).to be_empty
|
||||
@ -225,27 +211,6 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when message type is text' do
|
||||
let(:phone_number) { '5511912345678' }
|
||||
let(:jid) { "#{phone_number}@s.whatsapp.net" }
|
||||
let(:content_message) { 'Hello from Baileys' }
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: jid, fromMe: false },
|
||||
pushName: 'John Doe',
|
||||
message: { conversation: content_message }
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when has key conversation' do # rubocop:disable RSpec/NestedGroups
|
||||
it 'creates an incoming message' do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
@ -254,47 +219,46 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
message = conversation.messages.last
|
||||
|
||||
expect(message).to be_present
|
||||
expect(message.content).to eq(content_message)
|
||||
expect(message.content).to eq('Hello from Baileys')
|
||||
expect(message.sender).to be_present
|
||||
expect(message.sender.name).to eq('John Doe')
|
||||
expect(message.message_type).to eq('incoming')
|
||||
end
|
||||
|
||||
it 'creates an outgoing message' do
|
||||
raw_message_outgoing = raw_message.merge(key: { id: 'msg_123', remoteJid: jid, fromMe: true })
|
||||
params_outgoing = params.merge(data: { type: 'notify', messages: [raw_message_outgoing] })
|
||||
raw_message[:key][:fromMe] = true
|
||||
create(:account_user, account: inbox.account)
|
||||
|
||||
described_class.new(inbox: inbox, params: params_outgoing).perform
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
message = conversation.messages.last
|
||||
|
||||
expect(message).to be_present
|
||||
expect(message.content).to eq(content_message)
|
||||
expect(conversation.contact.name).to eq(phone_number)
|
||||
expect(message.content).to eq('Hello from Baileys')
|
||||
expect(conversation.contact.name).to eq('5511912345678')
|
||||
expect(message.message_type).to eq('outgoing')
|
||||
end
|
||||
|
||||
it 'creates an outgoing self message' do
|
||||
self_jid = "#{whatsapp_channel.phone_number.delete('+')}@s.whatsapp.net"
|
||||
raw_message_outgoing = raw_message.merge(key: { id: 'msg_123', remoteJid: self_jid, fromMe: true })
|
||||
params_outgoing = params.merge(data: { type: 'notify', messages: [raw_message_outgoing] })
|
||||
raw_message[:key][:remoteJid] = self_jid
|
||||
raw_message[:key][:fromMe] = true
|
||||
create(:account_user, account: inbox.account)
|
||||
|
||||
described_class.new(inbox: inbox, params: params_outgoing).perform
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
message = conversation.messages.last
|
||||
|
||||
expect(message).to be_present
|
||||
expect(message.content).to eq(content_message)
|
||||
expect(message.content).to eq('Hello from Baileys')
|
||||
expect(conversation.contact.name).to eq('John Doe')
|
||||
expect(message.message_type).to eq('outgoing')
|
||||
end
|
||||
|
||||
it 'updates the contact name when name is the phone number and message has a pushName' do
|
||||
create(:contact, account: inbox.account, name: phone_number)
|
||||
create(:contact, account: inbox.account, name: '5511912345678')
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
@ -304,7 +268,7 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
|
||||
it 'updates the contact name when name is the phone number and message has a verifiedBizName' do
|
||||
raw_message[:verifiedBizName] = 'Verified John'
|
||||
create(:contact, account: inbox.account, name: phone_number)
|
||||
create(:contact, account: inbox.account, name: '5511912345678')
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
@ -313,14 +277,13 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
it 'creates contact with phone number as name on outgoing message' do
|
||||
raw_message_outgoing = raw_message.merge(key: { id: 'msg_123', remoteJid: jid, fromMe: true })
|
||||
params_outgoing = params.merge(data: { type: 'notify', messages: [raw_message_outgoing] })
|
||||
raw_message[:key][:fromMe] = true
|
||||
create(:account_user, account: inbox.account)
|
||||
|
||||
described_class.new(inbox: inbox, params: params_outgoing).perform
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
expect(conversation.contact.name).to eq(phone_number)
|
||||
expect(conversation.contact.name).to eq('5511912345678')
|
||||
end
|
||||
|
||||
it 'creates a message on an existing conversation' do
|
||||
@ -364,15 +327,9 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when is a extendedTextMessage that has key text' do # rubocop:disable RSpec/NestedGroups
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { extendedTextMessage: { text: 'Hello from Baileys' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates an incoming message' do
|
||||
raw_message[:message] = { extendedTextMessage: { text: 'Hello from Baileys' } }
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
@ -387,33 +344,22 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when message type is reaction' do
|
||||
let(:phone_number) { '5511912345678' }
|
||||
let(:jid) { "#{phone_number}@s.whatsapp.net" }
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'reaction_123', remoteJid: jid, fromMe: false },
|
||||
message: { reactionMessage: { key: { remoteJid: jid, fromMe: true, id: 'msg_123' }, text: '👍' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
}
|
||||
}
|
||||
end
|
||||
let!(:message) do
|
||||
contact = create(:contact, account: inbox.account, name: phone_number)
|
||||
contact_inbox = create(:contact_inbox, inbox: inbox, contact: contact, source_id: phone_number)
|
||||
contact = create(:contact, account: inbox.account, name: '5511912345678')
|
||||
contact_inbox = create(:contact_inbox, inbox: inbox, contact: contact, source_id: '5511912345678')
|
||||
conversation = create(:conversation, inbox: inbox, contact_inbox: contact_inbox)
|
||||
create(:message, inbox: inbox, conversation: conversation, source_id: 'msg_123')
|
||||
end
|
||||
|
||||
it 'creates the reaction' do
|
||||
raw_message[:key][:id] = 'reaction_123'
|
||||
raw_message[:message] = {
|
||||
reactionMessage: {
|
||||
key: { remoteJid: '5511912345678@s.whatsapp.net', fromMe: true, id: 'msg_123' },
|
||||
text: '👍'
|
||||
}
|
||||
}
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
reaction = message.conversation.messages.last
|
||||
@ -423,7 +369,13 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
it 'does not create the reaction if content is empty' do
|
||||
raw_message[:message][:reactionMessage][:text] = ''
|
||||
raw_message[:key][:id] = 'reaction_123'
|
||||
raw_message[:message] = {
|
||||
reactionMessage: {
|
||||
key: { remoteJid: '5511912345678@s.whatsapp.net', fromMe: true, id: 'msg_123' },
|
||||
text: ''
|
||||
}
|
||||
}
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
@ -432,30 +384,14 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when message type is image' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { imageMessage: { caption: 'Hello from Baileys', mimetype: 'image/png' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
},
|
||||
extra: {
|
||||
media: {
|
||||
'msg_123' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='
|
||||
}
|
||||
it 'creates the message with caption' do
|
||||
raw_message[:message] = { imageMessage: { caption: 'Hello from Baileys', mimetype: 'image/png' } }
|
||||
params[:extra] = {
|
||||
media: {
|
||||
'msg_123' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates the message with caption' do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
conversation = inbox.conversations.last
|
||||
message = conversation.messages.last
|
||||
@ -465,6 +401,13 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
it 'creates message attachment' do
|
||||
raw_message[:message] = { imageMessage: { caption: 'Hello from Baileys', mimetype: 'image/png' } }
|
||||
params[:extra] = {
|
||||
media: {
|
||||
'msg_123' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='
|
||||
}
|
||||
}
|
||||
|
||||
freeze_time
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
@ -483,31 +426,16 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when message type is video' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { videoMessage: { caption: 'Hello from Baileys', mimetype: 'video/mp4' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
},
|
||||
extra: {
|
||||
media: {
|
||||
'msg_123' => 'AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAABL21kYXQAAAGzABAHAAABthGBxgj238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237wAAAbMAEAcAAAG2E4HGCkbckbbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237AAABswAQBwAAAbYVgcYLltyRtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfsAAAGzABAHAAABtheBxhPbckbbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237wAAAbMAEAcAAAG2GYHGJG3JG238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt+/AAADHW1vb3YAAABsbXZoZAAAAAAAAAAAAAAAAAAAA+gAAAPoAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAJHdHJhawAAAFx0a2hkAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAPoAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAABAAAAAQAAAAAAAJGVkdHMAAAAcZWxzdAAAAAAAAAABAAAD6AAAAAAAAQAAAAABv21kaWEAAAAgbWRoZAAAAAAAAAAAAAAAAAAAKAAAACgAVcQAAAAAAC1oZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAAAWptaW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAEqc3RibAAAAGJzdHNkAAAAAAAAACVhdmMxAAAAAAAAAAAAAAAAAACFc3R0cwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' # rubocop:disable Layout/LineLength
|
||||
}
|
||||
it 'creates the message with caption' do
|
||||
raw_message[:message] = { videoMessage: { caption: 'Hello from Baileys', mimetype: 'video/mp4' } }
|
||||
params[:extra] = {
|
||||
media: {
|
||||
'msg_123' => 'AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAABL21kYXQAAAGzABAHAAABthGBxgj238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237wAAAbMAEAcAAAG2E4HGCkbckbbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237AAABswAQBwAAAbYVgcYLltyRtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfsAAAGzABAHAAABtheBxhPbckbbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237wAAAbMAEAcAAAG2GYHGJG3JG238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt+/AAADHW1vb3YAAABsbXZoZAAAAAAAAAAAAAAAAAAAA+gAAAPoAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAJHdHJhawAAAFx0a2hkAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAPoAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAABAAAAAQAAAAAAAJGVkdHMAAAAcZWxzdAAAAAAAAAABAAAD6AAAAAAAAQAAAAABv21kaWEAAAAgbWRoZAAAAAAAAAAAAAAAAAAAKAAAACgAVcQAAAAAAC1oZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAAAWptaW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAEqc3RibAAAAGJzdHNkAAAAAAAAACVhdmMxAAAAAAAAAAAAAAAAAACFc3R0cwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' # rubocop:disable Layout/LineLength
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates the message with caption' do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
message = conversation.messages.last
|
||||
|
||||
@ -516,6 +444,13 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
it 'creates message attachment' do
|
||||
raw_message[:message] = { videoMessage: { caption: 'Hello from Baileys', mimetype: 'video/mp4' } }
|
||||
params[:extra] = {
|
||||
media: {
|
||||
'msg_123' => 'AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAABL21kYXQAAAGzABAHAAABthGBxgj238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237wAAAbMAEAcAAAG2E4HGCkbckbbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237AAABswAQBwAAAbYVgcYLltyRtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfsAAAGzABAHAAABtheBxhPbckbbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G237wAAAbMAEAcAAAG2GYHGJG3JG238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt/G238bbfxtt+/AAADHW1vb3YAAABsbXZoZAAAAAAAAAAAAAAAAAAAA+gAAAPoAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAJHdHJhawAAAFx0a2hkAAAAAwAAAAAAAAAAAAAAAQAAAAAAAAPoAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAABAAAAAQAAAAAAAJGVkdHMAAAAcZWxzdAAAAAAAAAABAAAD6AAAAAAAAQAAAAABv21kaWEAAAAgbWRoZAAAAAAAAAAAAAAAAAAAKAAAACgAVcQAAAAAAC1oZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAAAWptaW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAEqc3RibAAAAGJzdHNkAAAAAAAAACVhdmMxAAAAAAAAAAAAAAAAAACFc3R0cwAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' # rubocop:disable Layout/LineLength
|
||||
}
|
||||
}
|
||||
|
||||
freeze_time
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
@ -534,31 +469,14 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when message type is file' do
|
||||
let(:filename) { 'file.pdf' }
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { documentMessage: { fileName: filename } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
},
|
||||
extra: {
|
||||
media: {
|
||||
'msg_123' => 'JVBERi0xLjQKJVRlc3QgUERGCjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL091dGxpbmVzIDIgMCBSIC9QYWdlcyAzIDAgUiA+PgplbmRvYmoKMiAwIG9iago8PCAvVHlwZSAvT3V0bGluZXMgL0NvdW50IDAgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFs0IDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjQgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgCiAgIC9QYXJlbnQgMyAwIFIgCiAgIC9NZWRpYUJveCBbMCAwIDMwMCAyMDBdIAogICAvQ29udGVudHMgNSAwIFIgCiAgIC9SZXNvdXJjZXMgPDwgL0ZvbnQgPDwgL0YxIDw8IC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMSAvQmFzZUZvbnQgL0hlbHZldGljYSA+PiA+PiA+PgplbmRvYmoKNSAwIG9iago8PCAvTGVuZ3RoIDUzID4+CnN0cmVhbQpCVAovRjEgMTIgVGYKNzIgMTUwIFRkCihIZWxsbyBQREYhKSBUagpFVAplbmRzdHJlYW0KZW5kb2JqCnhyZWYKMCA2CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDAxNyAwMDAwMCBuIAowMDAwMDAwMDg0IDAwMDAwIG4gCjAwMDAwMDAxMzQgMDAwMDAgbiAKMDAwMDAwMDE5MyAwMDAwMCBuIAowMDAwMDAwMzkxIDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUgNiAvUm9vdCAxIDAgUiA+PgpzdGFydHhyZWYKNDk0CiUlRU9GCg==' # rubocop:disable Layout/LineLength
|
||||
}
|
||||
it 'creates message attachment' do
|
||||
raw_message[:message] = { documentMessage: { fileName: 'file.pdf' } }
|
||||
params[:extra] = {
|
||||
media: {
|
||||
'msg_123' => 'JVBERi0xLjQKJVRlc3QgUERGCjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL091dGxpbmVzIDIgMCBSIC9QYWdlcyAzIDAgUiA+PgplbmRvYmoKMiAwIG9iago8PCAvVHlwZSAvT3V0bGluZXMgL0NvdW50IDAgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFs0IDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjQgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgCiAgIC9QYXJlbnQgMyAwIFIgCiAgIC9NZWRpYUJveCBbMCAwIDMwMCAyMDBdIAogICAvQ29udGVudHMgNSAwIFIgCiAgIC9SZXNvdXJjZXMgPDwgL0ZvbnQgPDwgL0YxIDw8IC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMSAvQmFzZUZvbnQgL0hlbHZldGljYSA+PiA+PiA+PgplbmRvYmoKNSAwIG9iago8PCAvTGVuZ3RoIDUzID4+CnN0cmVhbQpCVAovRjEgMTIgVGYKNzIgMTUwIFRkCihIZWxsbyBQREYhKSBUagpFVAplbmRzdHJlYW0KZW5kb2JqCnhyZWYKMCA2CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDAxNyAwMDAwMCBuIAowMDAwMDAwMDg0IDAwMDAwIG4gCjAwMDAwMDAxMzQgMDAwMDAgbiAKMDAwMDAwMDE5MyAwMDAwMCBuIAowMDAwMDAwMzkxIDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUgNiAvUm9vdCAxIDAgUiA+PgpzdGFydHhyZWYKNDk0CiUlRU9GCg==' # rubocop:disable Layout/LineLength
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates message attachment' do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
@ -569,36 +487,20 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
expect(attachment.file_type).to eq('file')
|
||||
expect(attachment.file).to be_present
|
||||
|
||||
expect(attachment.file.filename.to_s).to eq(filename)
|
||||
expect(attachment.file.filename.to_s).to eq('file.pdf')
|
||||
expect(attachment.file.content_type).to eq('application/pdf')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message type is audio' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { audioMessage: { mimetype: 'audio/opus' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
},
|
||||
extra: {
|
||||
media: {
|
||||
'msg_123' => 'T2dnUwACAAAAAAAAAAAAAAAAAAAAACqCBoIBE09wdXNIZWFkAQFoAIA+AAAAAABPZ2dTAAAAAAAAAAAAAAAAAAABAAAAjzLsvAEYT3B1c1RhZ3MIAAAAV2hhdHNBcHAAAAAAT2dnUwAAqOwAAAAAAAAAAAAAAgAAAJ5agxUOav8T7PLg/wTu9t3/DodLhgcIBwcaC+TBNuzFgAfJcifhROpQB8l5yMlXwAfJecjJUbCAAtRK//E6OBUjAL9sWX+ZId5v5ZPVuy3VNIvDjKNuehMtIhui23+8zF6nYoLkqYj4YaZXn4AigNd5FYRrpMiu/XTgerAwS4YuLSstKYrWH82ADKXlHmIp2IXekQmEI3IMggeTCD0zjPEsIjeqmkVfAP/lesBo7ZRZyGCLBaIvPCArr1eTRWfFCFYEeO+o+RQff9NFmkO6LC3YaJWaZBzcqpkiVSZF9uCK1eJTZkGsApQno7t/iJlJqd1hmGvZzGeg/G1nzB8ps1s9Cb34YpDVU9KAiuJYr1hUxmfxI4KFiX2UtYdxGWNxfGRuwTVTqHmIPie2mdzzibieN1+k/2p0iuOf3GMaWMWtIPc7iARhMUBobiunslmmvirb1LmEx6Y3HbqH2suQoMqK1dzcuF13w1aWz0u+oBY1+tTxacRxmjZG7F3XcO5KaLhjrsYUK8CUnXEe1Zf5gEuGJywoISSK1dzX4aeizrE8N98P1sp6HXFxZNvRhHfXyXbn8zATmP04ts2x34CKYFWmnvrO1ktfF2v9MAFnvuRVZsFSXR9Hk+aYisrdrzcR21sxONbuV+YtS4ph2d9VdNkVZysVa9vLS367WyDKLRFRpxJYpHmRa0EagqNkzyoH8YCBYpnXXDIoSnW++SQs+aRcDrN94k4h1BydvZWT6yHRZEQzCk6563SEL1aa+0XxjdWVM7Udxke5uGW38hTwN59v2YsjzGYzOcNqxLHAh8XEJTZ8Pmlpy+8syby3YVGYDViXZWlkk70CH6F8S4YjJiciKzMjXqKr6GIbeou0Z2zKCclT+8+O5A5ALPLMswUcqkJGyPSoif7hX1AOdSFD+LO+G67VA3stP4FyPxS/DJyhPVKTLxM/oL2BCHSKAGw5BpS4CTxuzlErqMvCx5mDnbPOQtUamiaMu+dEXFLkeL7SXUAy+TMfscZ0qO4p6NCYAKs4tltZPSA0LVmn+Dh/6jxOj4ZwiZWLM95xHaF8CODilYJ+fHMBfu6cQ+xgaw5wBeACJxrXhs97LFaJBrPcMIm2XzjUP0yjCkG5eR2BqOSczSe3XJYYPi07mjVreHddvl+1sJTviKMNahmb8oBLhisgIx8lifjnzQv9W7jolZGOf2l1ndLQ+M3B7RCSidTGpjvfyhtzjZ2V6myBp2X3gDMjLxurEFNSF9pVl2W3ooe08Tnbxq2bQQIjguzU9Q/AgUn5o2rDGKeGdCQSsmlvtHOAvAEvh7wxb2c10bc6GafiQDIE+0MP4cZvqz6hsFQoSRDxO7Rug+EXlQc58Plptx+JMTvG2AbTjVmIMEgYMo07jI5Ipp6wB4L0E3hWDuNir/Q2jDWJQzE6gTLV4xN1TQANxXiE7t3R0ReTRlXLN0iUvaMTn7/F1GUAZSodeEuGLy0pKieJMabgzX2fGflllvjvVX88N22aJYnLzaWHjGOQSVJh10ioHIIOtQG5fgnhxr26MIkoyMZKr/U1MqvWIwdUOmi+ZLGs8bgEMmeFoMUV0gLagpxgeWcX8o5VFajuLy9PtrhU29mheHxO7PHnIn1xsarpbsHLl7n36q3zVB1TFwPWHlDvcFB8LWkJ1JJptzK1O4NTc29JT7WaEGaBVnjX/6eUOddKPqZz/lmOQYD1T1kgL1e0+Zhp3fOmaWb+pSh+HuqPU2wkmgo7imUOQ0mj6wDMbFIeQObwL1HKAZJzCdeBsug573apU5qYuV/ZEqYGJ0hQ74HnQ6ZvwqjwU05LhiEnJiImL1FTafh3rc8Cy7o/1/fyfT503ZbIZ5u62VtXZ4YY6xZWL1cs2qHiYShorlN/L46omeX4MtXZzVW7pKCzQdBhCeIla+dDbUfBL1FPWDH1cDGKCYp+jho2Cl1bL7vlaPsUkGWZ6Hl+bo4fqG9dFNgvUVhK7goJwHOWkY9v9rKLGNlaZ90LoOflGShWQh5lmTmAiSpm7GJTFSCi2hFKwHjEsitafxXWgy5Cw4I/XbPK0qRhJMFlZ3CBEnqAp9a+8ecaIq4fxNaMQNtkQ3N2Ks0C+7NwWXuFKLLyR1PrDg8Koij1IrlngnjAS4YvKCUmJ4m2XO+ECBolT/hH0hBp9oXO+Lr8lxC00+X/WtVnmK1epbZTbxucayw2yIFy012giZJ1UCUkkOlt6j6VRuueVyyAtn2y+8lVoDn0uC4yXFr5D7bqqLZ5gDEhg/rhoxAc/iwGS7DXkmgCE4DCn4rZI+gOYeA4cqDyM3Ry0rAwpQbfmnN4rpT8chKcqdGSFaXArxYaVbiGE4xHzj1m+XohGDcswy6/+NUFh1V3ZNlNL9Z86Ro2Uymmr2II/V1r3jRW47zP9wpk0CiiCC1aitUOTkDxlo4/Tac7mIdUvffnW9PHNp1Nry+nHC4MenwcNBlAS4YlIiMhJi1nFjHrzqG7NcfjjR/pGQ2HYwnigLJnP/8P9H3bDY3XBiURNqAtaIomrMImJrOqzDDvFi7vN2t+kmPIjZUPsQpD9586WfXeLWiTq3EhFDlzQ3vlA9wvo98iUzWXYHbgUCsQLpnWKc5YO8AtaIoD4ebsRtvk2oXKaYjHlDKgBfT745WEq+W6DzJ4gbAtaQG0PqxSKfrdvBbpPPkYL8gV/fwQPR51jvwKWt72JlEms7KbgC1P3UVmRscoNd6wKJQqP0mdrYd6BaXv2Yq1uKW6LhjMXbip6gpLhigpJi0vLWfCbps6OrJt07ZXi+x+IfoTJTfmByn3TbOAjvImlHsFtYH6AON6iC20TbaYXrCU6mMbQ5931swaz0YPEao/mRwbKMjzivLz8iEUVPUOETfYiSrSWWJND57daMlpJoTRZ0/DyBLf/aFV6rph8o7AdeOZo+1lNcCBNMd2BGZ+HSuHZdzV6Tl/VteFnl9Rk5Yz9j9f+H87ODuzHFb2et/nlPjOZDCKYpy8X5WIm4WI/p0O98FNV6Dl6gTPjA1iFlvBRgdmvLatWrk9EokU74otEJAf04qGJ/SMBzLIkfizWs/IdMWnWWJfB4eJcIIBFetNFJsADa1eOurprIiS1UMzm/aa1JmyoEuDLC6LY53aB2ceiPT3EUnJCBYscjp1sKigjAvQRHGd0pLWcsf+Ktf3NKcS2CJnIIqy7J9E0MerTxxbnsqkg2w33fSv92Jepqtp3O+Xv77vv1aVBQReQgXh4DIxUcmJ/xjFW4ARWdxQ9sSyOwGNV0k7LLNflhOPxqJJ7cRUiEXHsKZhYr0rZA==' # rubocop:disable Layout/LineLength
|
||||
}
|
||||
it 'creates message attachment' do
|
||||
raw_message[:message] = { audioMessage: { mimetype: 'audio/opus' } }
|
||||
params[:extra] = {
|
||||
media: {
|
||||
'msg_123' => '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' # rubocop:disable Layout/LineLength
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates message attachment' do
|
||||
freeze_time
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
@ -617,30 +519,14 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when message type is sticker' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { stickerMessage: { mimetype: 'image/png' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
},
|
||||
extra: {
|
||||
media: {
|
||||
'msg_123' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='
|
||||
}
|
||||
it 'creates message attachment' do
|
||||
raw_message[:message] = { stickerMessage: { mimetype: 'image/png' } }
|
||||
params[:extra] = {
|
||||
media: {
|
||||
'msg_123' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates message attachment' do
|
||||
freeze_time
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
@ -660,23 +546,21 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when processing messages.update event' do
|
||||
context 'when message is not found' do
|
||||
let(:message_id) { 'msg_123' }
|
||||
let(:update_payload) do
|
||||
{
|
||||
key: { id: message_id },
|
||||
update: {
|
||||
status: 2
|
||||
}
|
||||
}
|
||||
end
|
||||
let!(:message) { create(:message, source_id: 'msg_123', status: 'sent') }
|
||||
let(:update_payload) do
|
||||
{ key: { id: 'msg_123' }, update: { status: 3 } }
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.update',
|
||||
data: [update_payload]
|
||||
}
|
||||
end
|
||||
|
||||
context 'when message is not found' do
|
||||
it 'raises MessageNotFoundError' do
|
||||
params = {
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.update',
|
||||
data: [update_payload]
|
||||
}
|
||||
update_payload[:key][:id] = 'no_message_id'
|
||||
|
||||
expect do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
@ -685,34 +569,14 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when message is found' do
|
||||
let(:message_id) { 'msg_123' }
|
||||
let!(:message) { create(:message, source_id: message_id, status: 'sent') }
|
||||
|
||||
it 'updates the message status' do
|
||||
update_payload = { key: { id: message_id }, update: { status: 3 } }
|
||||
params = {
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.update',
|
||||
data: [update_payload]
|
||||
}
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
expect(message.reload.status).to eq('delivered')
|
||||
end
|
||||
|
||||
it 'updates the message content' do
|
||||
update_payload = {
|
||||
key: { id: message_id },
|
||||
update: {
|
||||
message: { editedMessage: { message: { conversation: 'New message content' } } }
|
||||
}
|
||||
}
|
||||
params = {
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.update',
|
||||
data: [update_payload]
|
||||
}
|
||||
update_payload[:update] = { message: { editedMessage: { message: { conversation: 'New message content' } } } }
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
@ -724,16 +588,8 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when the status transition is not allowed (message already read)' do
|
||||
let(:message_id) { 'msg_123' }
|
||||
let!(:message) { create(:message, source_id: message_id, status: 'read') }
|
||||
|
||||
it 'does not update the status' do
|
||||
update_payload = { key: { id: message_id }, update: { status: 3 } }
|
||||
params = {
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.update',
|
||||
data: [update_payload]
|
||||
}
|
||||
message.update!(status: 'read')
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
@ -742,16 +598,9 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
context 'when update unsupported status' do
|
||||
let(:message_id) { 'msg_123' }
|
||||
let!(:message) { create(:message, source_id: message_id) } # rubocop:disable RSpec/LetSetup
|
||||
|
||||
it 'logs warning for unsupported played status' do
|
||||
update_payload = { key: { id: message_id }, update: { status: 5 } }
|
||||
params = {
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.update',
|
||||
data: [update_payload]
|
||||
}
|
||||
update_payload[:update][:status] = 5
|
||||
|
||||
allow(Rails.logger).to receive(:warn).with('Baileys unsupported message update status: PLAYED(5)')
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
@ -760,12 +609,8 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
it 'logs warning for unsupported status' do
|
||||
update_payload = { key: { id: message_id }, update: { status: 6 } }
|
||||
params = {
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.update',
|
||||
data: [update_payload]
|
||||
}
|
||||
update_payload[:update][:status] = 6
|
||||
|
||||
allow(Rails.logger).to receive(:warn).with('Baileys unsupported message update status: 6')
|
||||
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
Loading…
Reference in New Issue
Block a user