Adds an account-level setting `keep_pending_on_bot_failure` to control whether conversations should move from pending to open when agent bot webhooks fail. Some users experience occasional message drops and don't want conversations to automatically reopen due to transient bot failures. This setting gives accounts control over that behavior. This is a temporary setting which will be removed in future once a proper fix for it is done, so it is not added in the UI.
110 lines
3.4 KiB
Ruby
110 lines
3.4 KiB
Ruby
require 'rails_helper'
|
|
|
|
describe Webhooks::Trigger do
|
|
include ActiveJob::TestHelper
|
|
|
|
subject(:trigger) { described_class }
|
|
|
|
let!(:account) { create(:account) }
|
|
let!(:inbox) { create(:inbox, account: account) }
|
|
let!(:conversation) { create(:conversation, inbox: inbox) }
|
|
let!(:message) { create(:message, account: account, inbox: inbox, conversation: conversation) }
|
|
|
|
let(:webhook_type) { :api_inbox_webhook }
|
|
let!(:url) { 'https://test.com' }
|
|
let(:agent_bot_error_content) { I18n.t('conversations.activity.agent_bot.error_moved_to_open') }
|
|
let(:default_timeout) { 5 }
|
|
let(:webhook_timeout) { default_timeout }
|
|
|
|
before do
|
|
ActiveJob::Base.queue_adapter = :test
|
|
allow(GlobalConfig).to receive(:get_value).and_call_original
|
|
allow(GlobalConfig).to receive(:get_value).with('WEBHOOK_TIMEOUT').and_return(webhook_timeout)
|
|
allow(GlobalConfig).to receive(:get_value).with('DEPLOYMENT_ENV').and_return(nil)
|
|
end
|
|
|
|
after do
|
|
clear_enqueued_jobs
|
|
clear_performed_jobs
|
|
end
|
|
|
|
describe '#execute' do
|
|
it 'triggers webhook' do
|
|
payload = { hello: :hello }
|
|
|
|
expect(RestClient::Request).to receive(:execute)
|
|
.with(
|
|
method: :post,
|
|
url: url,
|
|
payload: payload.to_json,
|
|
headers: { content_type: :json, accept: :json },
|
|
timeout: webhook_timeout
|
|
).once
|
|
trigger.execute(url, payload, webhook_type)
|
|
end
|
|
|
|
it 'raises RetriableError when webhook fails' do
|
|
payload = { event: 'message_created', conversation: { id: conversation.id }, id: message.id }
|
|
|
|
expect(RestClient::Request).to receive(:execute)
|
|
.with(
|
|
method: :post,
|
|
url: url,
|
|
payload: payload.to_json,
|
|
headers: { content_type: :json, accept: :json },
|
|
timeout: webhook_timeout
|
|
).and_raise(RestClient::ExceptionWithResponse.new('error', 500)).once
|
|
|
|
expect { trigger.execute(url, payload, webhook_type) }.to raise_error(CustomExceptions::Webhook::RetriableError)
|
|
end
|
|
|
|
it 'does not call ErrorHandler directly (deferred to job discard)' do
|
|
payload = { event: 'message_created', conversation: { id: conversation.id }, id: message.id }
|
|
|
|
expect(RestClient::Request).to receive(:execute)
|
|
.and_raise(RestClient::ExceptionWithResponse.new('error', 500))
|
|
|
|
expect(Webhooks::ErrorHandler).not_to receive(:perform)
|
|
expect { trigger.execute(url, payload, webhook_type) }.to raise_error(CustomExceptions::Webhook::RetriableError)
|
|
end
|
|
end
|
|
|
|
context 'when webhook timeout configuration is blank' do
|
|
let(:webhook_timeout) { nil }
|
|
|
|
it 'falls back to default timeout' do
|
|
payload = { hello: :hello }
|
|
|
|
expect(RestClient::Request).to receive(:execute)
|
|
.with(
|
|
method: :post,
|
|
url: url,
|
|
payload: payload.to_json,
|
|
headers: { content_type: :json, accept: :json },
|
|
timeout: default_timeout
|
|
).once
|
|
|
|
trigger.execute(url, payload, webhook_type)
|
|
end
|
|
end
|
|
|
|
context 'when webhook timeout configuration is invalid' do
|
|
let(:webhook_timeout) { -1 }
|
|
|
|
it 'falls back to default timeout' do
|
|
payload = { hello: :hello }
|
|
|
|
expect(RestClient::Request).to receive(:execute)
|
|
.with(
|
|
method: :post,
|
|
url: url,
|
|
payload: payload.to_json,
|
|
headers: { content_type: :json, accept: :json },
|
|
timeout: default_timeout
|
|
).once
|
|
|
|
trigger.execute(url, payload, webhook_type)
|
|
end
|
|
end
|
|
end
|