Files
chatwoot/spec/presenters/conversations/event_data_presenter_spec.rb
af1dfc21f6 fix: include account data in webhook payloads (#12445)
Conversation and inbox webhook payloads now include the account object
(`{ id, name }`) so integrations can reliably identify the account
without depending on nested message data.

## Closes

Closes #11753
Closes #12442

## Why

Message, contact, and contact inbox webhook payloads already expose
`account`. Conversation and inbox webhook payloads were outliers, which
forced webhook consumers to infer account context from nested messages
or other fields that may not always be present.

## What changed

- Adds `account: { id, name }` to conversation webhook payloads.
- Adds webhook-specific inbox payload data with `account: { id, name }`
for inbox created/updated events.
- Keeps non-webhook conversation and inbox push payload behavior
unchanged.

## How to test

- Configure an account webhook for `conversation_created`, trigger a new
conversation, and confirm the webhook payload includes `account.id` and
`account.name`.
- Configure an account webhook for `inbox_created`, create a new inbox,
and confirm the webhook payload includes `account.id` and
`account.name`.
- Configure a webhook agent bot and update a conversation status, then
confirm the bot webhook payload includes the same account object.

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-06-09 12:12:46 +05:30

77 lines
2.8 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Conversations::EventDataPresenter do
let(:presenter) { described_class.new(conversation) }
let(:conversation) { create(:conversation) }
describe '#push_data' do
let(:expected_data) do
{
additional_attributes: {},
meta: {
sender: conversation.contact.push_event_data,
assignee: conversation.assigned_entity&.push_event_data,
assignee_type: conversation.assignee_type,
team: conversation.team&.push_event_data,
hmac_verified: conversation.contact_inbox.hmac_verified
},
id: conversation.display_id,
messages: [],
labels: [],
inbox_id: conversation.inbox_id,
status: conversation.status,
contact_inbox: conversation.contact_inbox,
can_reply: conversation.can_reply?,
channel: conversation.inbox.channel_type,
timestamp: conversation.last_activity_at.to_i,
snoozed_until: conversation.snoozed_until,
custom_attributes: conversation.custom_attributes,
first_reply_created_at: nil,
contact_last_seen_at: conversation.contact_last_seen_at.to_i,
agent_last_seen_at: conversation.agent_last_seen_at.to_i,
created_at: conversation.created_at.to_i,
updated_at: conversation.updated_at.to_f,
waiting_since: conversation.waiting_since.to_i,
priority: nil,
unread_count: 0
}
end
it 'returns push event payload' do
# the exceptions are the values that would be added in enterprise edition.
expect(presenter.push_data.except(:applied_sla, :sla_events)).to include(expected_data)
end
end
describe '#webhook_data' do
it 'includes account details for webhook consumers' do
expect(presenter.webhook_data[:account]).to eq(conversation.account.webhook_data)
end
it 'normalizes hard-break backslashes in message content' do
message = create(:message, conversation: conversation, account: conversation.account,
message_type: :outgoing, content: "Hello\\\nWorld")
data = presenter.webhook_data
webhook_message = data[:messages].first
expect(webhook_message).to be_present
expect(webhook_message[:content]).to eq("Hello\nWorld")
expect(webhook_message[:id]).to eq(message.id)
end
it 'preserves normal newlines in message content' do
create(:message, conversation: conversation, account: conversation.account,
message_type: :outgoing, content: "Line one\n\nLine two")
webhook_message = presenter.webhook_data[:messages].first
expect(webhook_message[:content]).to eq("Line one\n\nLine two")
end
it 'returns empty messages when conversation has no chat messages' do
expect(presenter.webhook_data[:messages]).to eq([])
end
end
end