This upgrades Chatwoot to Rails 7.2.3.1 while retaining the current Rails 7.0 framework defaults, so the runtime upgrade can be deployed and observed independently from default-behavior changes. ## What changed - Upgrade Rails and the compatible dependency set to Rails 7.2.3.1. - Keep `config.load_defaults 7.0` for a staged, lower-risk rollout. - Replace the unmaintained Azure Active Storage fork with the maintained `azure-blob` adapter while preserving the `microsoft` service name. - Pin Sidekiq 7.3.10 with `connection_pool` 2.x after validating scheduled-job execution against Redis. - Update Rails 7.2 compatibility surfaces in Active Record, strong parameters, migrations, storage, and tests. - Add read-only production preflight checks, an opt-in Active Storage smoke script, a deployment runbook, and the full Rails 7.2/8.0/8.1 assessment. ## How to test 1. Sign in and verify the dashboard and conversation UI load normally. 2. Open the agent-management modal and confirm agent data is rendered. 3. Create an API inbox and wait for the asynchronous deletion flow to complete. 4. Open Super Admin pages, including instance status and account-user management. 5. Upload and download an attachment using the configured Active Storage service. 6. Confirm recurring Sidekiq Cron jobs register and execute after startup. ## Rollout Follow `docs/rails_upgrades/7_2.md` for pre-deploy checks, deployment order, smoke tests, monitoring, and rollback. Run `bundle exec rails runner script/rails_upgrade/preflight.rb` against a production-equivalent environment before rollout. ## Tracking - [CW-5863 — Upgrade Rails to 8+](https://linear.app/chatwoot/issue/CW-5863/upgrade-rails-to-8) - [Rails 7.2 to 8.1 upgrade and production rollout plan](https://linear.app/chatwoot/document/chatwoot-rails-72-to-81-upgrade-and-production-rollout-plan-44e9f4964cb2) --------- Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> Co-authored-by: Sony Mathew <2040199+sony-mathew@users.noreply.github.com> Co-authored-by: Sony Mathew <sony@chatwoot.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
601 lines
26 KiB
Ruby
601 lines
26 KiB
Ruby
require 'rails_helper'
|
|
|
|
describe Telegram::IncomingMessageService do
|
|
before do
|
|
stub_request(:any, /api.telegram.org/).to_return(headers: { content_type: 'application/json' }, body: {}.to_json, status: 200)
|
|
stub_request(:get, 'https://chatwoot-assets.local/sample.png').to_return(
|
|
status: 200,
|
|
body: File.read('spec/assets/sample.png'),
|
|
headers: {}
|
|
)
|
|
stub_request(:get, 'https://chatwoot-assets.local/sample.mov').to_return(
|
|
status: 200,
|
|
body: File.read('spec/assets/sample.mov'),
|
|
headers: {}
|
|
)
|
|
stub_request(:get, 'https://chatwoot-assets.local/sample.mp3').to_return(
|
|
status: 200,
|
|
body: File.read('spec/assets/sample.mp3'),
|
|
headers: {}
|
|
)
|
|
stub_request(:get, 'https://chatwoot-assets.local/sample.ogg').to_return(
|
|
status: 200,
|
|
body: File.read('spec/assets/sample.ogg'),
|
|
headers: {}
|
|
)
|
|
stub_request(:get, 'https://chatwoot-assets.local/sample.pdf').to_return(
|
|
status: 200,
|
|
body: File.read('spec/assets/sample.pdf'),
|
|
headers: {}
|
|
)
|
|
end
|
|
|
|
let!(:telegram_channel) { create(:channel_telegram) }
|
|
let!(:message_params) do
|
|
{
|
|
'message_id' => 1,
|
|
'from' => {
|
|
'id' => 23, 'is_bot' => false, 'first_name' => 'Sojan', 'last_name' => 'Jose', 'username' => 'sojan', 'language_code' => 'en'
|
|
},
|
|
'chat' => { 'id' => 23, 'first_name' => 'Sojan', 'last_name' => 'Jose', 'username' => 'sojan', 'type' => 'private' },
|
|
'date' => 1_631_132_077
|
|
}
|
|
end
|
|
|
|
def contact_for(source_id = nil)
|
|
source_id ||= message_params.dig('from', 'id')
|
|
ContactInbox.find_by!(inbox: telegram_channel.inbox, source_id: source_id).contact
|
|
end
|
|
|
|
describe '#perform' do
|
|
context 'when valid text message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'text' => 'test' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.content).to eq('test')
|
|
end
|
|
end
|
|
|
|
context 'when valid caption params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'caption' => 'test' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(contact_for.additional_attributes['social_telegram_user_id']).to eq(23)
|
|
expect(contact_for.additional_attributes['social_telegram_user_name']).to eq('sojan')
|
|
expect(telegram_channel.inbox.messages.first.content).to eq('test')
|
|
end
|
|
end
|
|
|
|
context 'when group messages' do
|
|
it 'doesnot create conversations, message and contacts' do
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'message_id' => 1,
|
|
'from' => {
|
|
'id' => 23, 'is_bot' => false, 'first_name' => 'Sojan', 'last_name' => 'Jose', 'username' => 'sojan', 'language_code' => 'en'
|
|
},
|
|
'chat' => { 'id' => 23, 'first_name' => 'Sojan', 'last_name' => 'Jose', 'username' => 'sojan', 'type' => 'group' },
|
|
'date' => 1_631_132_077, 'text' => 'test'
|
|
}
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context 'when business connection messages' do
|
|
subject do
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
end
|
|
|
|
let(:business_message_params) { message_params.merge('business_connection_id' => 'eooW3KF5WB5HxTD7T826') }
|
|
let(:params) do
|
|
{
|
|
'update_id' => 2_342_342_343_242,
|
|
'business_message' => { 'text' => 'test' }.deep_merge(business_message_params)
|
|
}.with_indifferent_access
|
|
end
|
|
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
subject
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(telegram_channel.inbox.conversations.last.additional_attributes).to include({ 'chat_id' => 23,
|
|
'business_connection_id' => 'eooW3KF5WB5HxTD7T826' })
|
|
contact = contact_for
|
|
expect(contact.name).to eq('Sojan Jose')
|
|
expect(contact.additional_attributes['language_code']).to eq('en')
|
|
message = telegram_channel.inbox.messages.first
|
|
expect(message.content).to eq('test')
|
|
expect(message.message_type).to eq('incoming')
|
|
expect(message.sender).to eq(contact)
|
|
end
|
|
|
|
context 'when sender is your business account' do
|
|
let(:business_message_params) do
|
|
message_params.merge(
|
|
'business_connection_id' => 'eooW3KF5WB5HxTD7T826',
|
|
'from' => {
|
|
'id' => 42, 'is_bot' => false, 'first_name' => 'John', 'last_name' => 'Doe', 'username' => 'johndoe', 'language_code' => 'en'
|
|
}
|
|
)
|
|
end
|
|
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
subject
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(telegram_channel.inbox.conversations.last.additional_attributes).to include({ 'chat_id' => 23,
|
|
'business_connection_id' => 'eooW3KF5WB5HxTD7T826' })
|
|
contact = contact_for
|
|
expect(contact.name).to eq('Sojan Jose')
|
|
# TODO: The language code is not present when we send the first message to the client.
|
|
# Should we update it when the user replies?
|
|
expect(contact.additional_attributes['language_code']).to be_nil
|
|
message = telegram_channel.inbox.messages.first
|
|
expect(message.content).to eq('test')
|
|
expect(message.message_type).to eq('outgoing')
|
|
expect(message.sender).to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when valid audio messages params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.mp3')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'audio' => {
|
|
'file_id' => 'AwADBAADbXXXXXXXXXXXGBdhD2l6_XX',
|
|
'duration' => 243,
|
|
'mime_type' => 'audio/mpeg',
|
|
'file_size' => 3_897_500,
|
|
'title' => 'Test music file'
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(contact_for.additional_attributes['social_telegram_user_id']).to eq(23)
|
|
expect(contact_for.additional_attributes['social_telegram_user_name']).to eq('sojan')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('audio')
|
|
end
|
|
end
|
|
|
|
context 'when valid image attachment params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.png')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'photo' => [{
|
|
'file_id' => 'AgACAgUAAxkBAAODYV3aGZlD6vhzKsE2WNmblsr6zKwAAi-tMRvCoeBWNQ1ENVBzJdwBAAMCAANzAAMhBA',
|
|
'file_unique_id' => 'AQADL60xG8Kh4FZ4', 'file_size' => 1883, 'width' => 90, 'height' => 67
|
|
}]
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('image')
|
|
end
|
|
end
|
|
|
|
context 'when valid sticker attachment params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.png')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'sticker' => {
|
|
'emoji' => '👍', 'width' => 512, 'height' => 512, 'set_name' => 'a834556273_by_HopSins_1_anim', 'is_animated' => 1,
|
|
'thumb' => {
|
|
'file_id' => 'AAMCAQADGQEAA0dhXpKorj9CiRpNX3QOn7YPZ6XS4AAC4wADcVG-MexptyOf8SbfAQAHbQADIQQ',
|
|
'file_unique_id' => 'AQAD4wADcVG-MXI', 'file_size' => 4690, 'width' => 128, 'height' => 128
|
|
},
|
|
'file_id' => 'CAACAgEAAxkBAANHYV6SqK4_QokaTV90Dp-2D2el0uAAAuMAA3FRvjHsabcjn_Em3yEE',
|
|
'file_unique_id' => 'AgAD4wADcVG-MQ',
|
|
'file_size' => 7340
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('image')
|
|
end
|
|
end
|
|
|
|
context 'when valid video messages params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.mov')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'video' => {
|
|
'duration' => 1, 'width' => 720, 'height' => 1280, 'file_name' => 'IMG_2170.MOV', 'mime_type' => 'video/mp4', 'thumb' => {
|
|
'file_id' => 'AAMCBQADGQEAA4ZhXd78Xz6_c6gCzbdIkgGiXJcwwwACqwMAAp3x8Fbhf3EWamgCWAEAB20AAyEE', 'file_unique_id' => 'AQADqwMAAp3x8FZy',
|
|
'file_size' => 11_462, 'width' => 180, 'height' => 320
|
|
}, 'file_id' => 'BAACAgUAAxkBAAOGYV3e_F8-v3OoAs23SJIBolyXMMMAAqsDAAKd8fBW4X9xFmpoAlghBA', 'file_unique_id' => 'AgADqwMAAp3x8FY',
|
|
'file_size' => 291_286
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('video')
|
|
end
|
|
end
|
|
|
|
context 'when valid video_note messages params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.mov')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'video_note' => {
|
|
'duration' => 3,
|
|
'length' => 240,
|
|
'thumb' => {
|
|
'file_id' => 'AAMCBQADGQEAA4ZhXd78Xz6_c6gCzbdIkgGiXJcwwwACqwMAAp3x8Fbhf3EWamgCWAEAB20AAyEE',
|
|
'file_unique_id' => 'AQADqwMAAp3x8FZy',
|
|
'file_size' => 11_462,
|
|
'width' => 240,
|
|
'height' => 240
|
|
},
|
|
'file_id' => 'DQACAgUAAxkBAAIBY2FdJlhf8PC2E3IalXSvXWO5m8GBAALJAwACwqHgVhb0truM0uhwIQQ',
|
|
'file_unique_id' => 'AgADyQMAAsKh4FY',
|
|
'file_size' => 132_446
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('video')
|
|
end
|
|
end
|
|
|
|
context 'when valid voice attachment params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.ogg')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'voice' => {
|
|
'duration' => 2, 'mime_type' => 'audio/ogg', 'file_id' => 'AwACAgUAAxkBAANjYVwnWF_w8LYTchqVdK9dY7mbwYEAAskDAALCoeBWFvS2u4zS6HAhBA',
|
|
'file_unique_id' => 'AgADyQMAAsKh4FY', 'file_size' => 11_833
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('audio')
|
|
end
|
|
end
|
|
|
|
context 'when valid document message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.pdf')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'document' => {
|
|
'file_id' => 'AwADBAADbXXXXXXXXXXXGBdhD2l6_XX',
|
|
'file_name' => 'Screenshot 2021-09-27 at 2.01.14 PM.png',
|
|
'mime_type' => 'application/png',
|
|
'file_size' => 536_392
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
attachment = telegram_channel.inbox.messages.first.attachments.first
|
|
expect(attachment.file_type).to eq('file')
|
|
# Retain the original filename from the payload instead of Telegram's internal download name
|
|
expect(attachment.file.filename.to_s).to eq('Screenshot 2021-09-27 at 2.01.14 PM.png')
|
|
end
|
|
end
|
|
|
|
context 'when attachment params have no file_name' do
|
|
it 'falls back to the downloaded file name' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return('https://chatwoot-assets.local/sample.png')
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'photo' => [{
|
|
'file_id' => 'AgACAgUAAxkBAAODYV3aGZlD6vhzKsE2WNmblsr6zKwAAi-tMRvCoeBWNQ1ENVBzJdwBAAMCAANzAAMhBA',
|
|
'file_unique_id' => 'AQADL60xG8Kh4FZ4', 'file_size' => 1883, 'width' => 90, 'height' => 67
|
|
}]
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
attachment = telegram_channel.inbox.messages.first.attachments.first
|
|
expect(attachment.file_type).to eq('image')
|
|
expect(attachment.file.filename.to_s).to eq('sample.png')
|
|
end
|
|
end
|
|
|
|
context 'when the API call to get the download path returns an error' do
|
|
it 'does not process the attachment' do
|
|
allow(telegram_channel.inbox.channel).to receive(:get_telegram_file_path).and_return(nil)
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'document' => {
|
|
'file_id' => 'AwADBAADbXXXXXXXXXXXGBdhD2l6_XX',
|
|
'file_name' => 'Screenshot 2021-09-27 at 2.01.14 PM.png',
|
|
'mime_type' => 'application/png',
|
|
'file_size' => 536_392
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.messages.first.attachments.count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context 'when valid location message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'location': {
|
|
'latitude': 37.7893768,
|
|
'longitude': -122.3895553
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('location')
|
|
end
|
|
|
|
it 'creates appropriate conversations, message and contacts if venue is present' do
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'location': {
|
|
'latitude': 37.7893768,
|
|
'longitude': -122.3895553
|
|
},
|
|
venue: {
|
|
title: 'San Francisco'
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
|
|
attachment = telegram_channel.inbox.messages.first.attachments.first
|
|
expect(attachment.file_type).to eq('location')
|
|
expect(attachment.coordinates_lat).to eq(37.7893768)
|
|
expect(attachment.coordinates_long).to eq(-122.3895553)
|
|
expect(attachment.fallback_title).to eq('San Francisco')
|
|
end
|
|
end
|
|
|
|
context 'when valid callback_query params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'callback_query' => {
|
|
'id' => '2342342309929423',
|
|
'from' => {
|
|
'id' => 5_171_248,
|
|
'is_bot' => false,
|
|
'first_name' => 'Sojan',
|
|
'last_name' => 'Jose',
|
|
'username' => 'sojan',
|
|
'language_code' => 'en',
|
|
'is_premium' => true
|
|
},
|
|
'message' => message_params,
|
|
'chat_instance' => '-89923842384923492',
|
|
'data' => 'Option 1'
|
|
}
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for(5_171_248).name).to eq('Sojan Jose')
|
|
expect(contact_for(5_171_248).additional_attributes['social_telegram_user_id']).to eq(5_171_248)
|
|
expect(telegram_channel.inbox.messages.first.content).to eq('Option 1')
|
|
end
|
|
end
|
|
|
|
context 'when valid contact message params' do
|
|
it 'creates appropriate conversations, message and contacts' do
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => {
|
|
'contact': {
|
|
'phone_number': '+918660944581'
|
|
}
|
|
}.merge(message_params)
|
|
}.with_indifferent_access
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
expect(telegram_channel.inbox.conversations.count).not_to eq(0)
|
|
expect(contact_for.name).to eq('Sojan Jose')
|
|
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('contact')
|
|
end
|
|
end
|
|
|
|
context 'when lock_to_single_conversation is false' do
|
|
before do
|
|
telegram_channel.inbox.update(lock_to_single_conversation: false)
|
|
end
|
|
|
|
it 'creates a new conversation when all previous conversations are resolved' do
|
|
# Create a contact and a resolved conversation
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'text' => 'first message' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
|
|
# Mark the conversation as resolved
|
|
conversation = telegram_channel.inbox.conversations.last
|
|
conversation.update(status: :resolved)
|
|
|
|
# Send a new message
|
|
new_params = {
|
|
'update_id' => 2_342_342_343_243,
|
|
'message' => { 'text' => 'second message' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: new_params).perform
|
|
|
|
# Should create a new conversation
|
|
expect(telegram_channel.inbox.conversations.count).to eq(2)
|
|
expect(telegram_channel.inbox.conversations.last.messages.first.content).to eq('second message')
|
|
end
|
|
|
|
it 'uses the existing conversation when there is an unresolved conversation' do
|
|
# Create a contact and an unresolved conversation
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'text' => 'first message' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
|
|
# Send a new message
|
|
new_params = {
|
|
'update_id' => 2_342_342_343_243,
|
|
'message' => { 'text' => 'second message' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: new_params).perform
|
|
|
|
# Should use the same conversation
|
|
expect(telegram_channel.inbox.conversations.count).to eq(1)
|
|
expect(telegram_channel.inbox.conversations.last.messages.count).to eq(2)
|
|
expect(telegram_channel.inbox.conversations.last.messages.last.content).to eq('second message')
|
|
end
|
|
end
|
|
|
|
context 'when lock_to_single_conversation is true' do
|
|
before do
|
|
telegram_channel.inbox.update(lock_to_single_conversation: true)
|
|
end
|
|
|
|
it 'uses the existing conversation even when it is resolved' do
|
|
# Create a contact and a resolved conversation
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'text' => 'first message' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
|
|
# Mark the conversation as resolved
|
|
conversation = telegram_channel.inbox.conversations.last
|
|
conversation.update(status: :resolved)
|
|
|
|
# Send a new message
|
|
new_params = {
|
|
'update_id' => 2_342_342_343_243,
|
|
'message' => { 'text' => 'second message' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: new_params).perform
|
|
|
|
# Should use the same conversation
|
|
expect(telegram_channel.inbox.conversations.count).to eq(1)
|
|
expect(telegram_channel.inbox.conversations.last.messages.count).to eq(2)
|
|
expect(telegram_channel.inbox.conversations.last.messages.last.content).to eq('second message')
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when lock to single conversation is enabled' do
|
|
before do
|
|
# ensure message_params exists in this context and has from.id
|
|
message_params[:from] ||= {}
|
|
message_params[:from][:id] ||= 23
|
|
end
|
|
|
|
it 'reopens last conversation if last conversation is resolved' do
|
|
telegram_channel.inbox.update!(lock_to_single_conversation: true)
|
|
contact_inbox = ContactInbox.find_or_create_by(inbox: telegram_channel.inbox, source_id: message_params[:from][:id]) do |ci|
|
|
ci.contact = create(:contact)
|
|
end
|
|
resolved_conversation = create(:conversation, inbox: telegram_channel.inbox, contact_inbox: contact_inbox, status: :resolved)
|
|
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'text' => 'test' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
|
|
expect(telegram_channel.inbox.conversations.count).to eq(1)
|
|
expect(resolved_conversation.reload.messages.last.content).to eq('test')
|
|
end
|
|
end
|
|
|
|
context 'when lock to single conversation is disabled' do
|
|
before do
|
|
# ensure message_params exists in this context and has from.id
|
|
message_params[:from] ||= {}
|
|
message_params[:from][:id] ||= 23
|
|
end
|
|
|
|
it 'creates new conversation if last conversation is resolved' do
|
|
telegram_channel.inbox.update!(lock_to_single_conversation: false)
|
|
contact_inbox = ContactInbox.find_or_create_by(inbox: telegram_channel.inbox, source_id: message_params[:from][:id]) do |ci|
|
|
ci.contact = create(:contact)
|
|
end
|
|
_resolved_conversation = create(:conversation, inbox: telegram_channel.inbox, contact_inbox: contact_inbox, status: :resolved)
|
|
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'text' => 'test' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
|
|
expect(telegram_channel.inbox.conversations.count).to eq(2)
|
|
expect(telegram_channel.inbox.conversations.last.messages.first.content).to eq('test')
|
|
expect(telegram_channel.inbox.conversations.last.status).to eq('open')
|
|
end
|
|
|
|
it 'appends to last conversation if last conversation is not resolved' do
|
|
telegram_channel.inbox.update!(lock_to_single_conversation: false)
|
|
contact_inbox = ContactInbox.find_or_create_by(inbox: telegram_channel.inbox, source_id: message_params[:from][:id]) do |ci|
|
|
ci.contact = create(:contact)
|
|
end
|
|
open_conversation = create(:conversation, inbox: telegram_channel.inbox, contact_inbox: contact_inbox, status: :open)
|
|
|
|
params = {
|
|
'update_id' => 2_342_342_343_242,
|
|
'message' => { 'text' => 'test' }.merge(message_params)
|
|
}.with_indifferent_access
|
|
|
|
described_class.new(inbox: telegram_channel.inbox, params: params).perform
|
|
|
|
expect(telegram_channel.inbox.conversations.count).to eq(1)
|
|
expect(open_conversation.reload.messages.last.content).to eq('test')
|
|
end
|
|
end
|
|
end
|