feat: Add APIs for Dialogflow integration V1 (#2155)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
FactoryBot.define do
|
||||
factory :integrations_hook, class: 'Integrations::Hook' do
|
||||
status { 1 }
|
||||
inbox_id { 1 }
|
||||
account_id { 1 }
|
||||
status { Integrations::Hook.statuses['enabled'] }
|
||||
inbox
|
||||
account
|
||||
app_id { 'slack' }
|
||||
settings { 'MyText' }
|
||||
hook_type { 1 }
|
||||
settings { { 'test': 'test' } }
|
||||
hook_type { Integrations::Hook.statuses['account'] }
|
||||
access_token { SecureRandom.hex }
|
||||
reference_id { SecureRandom.hex }
|
||||
end
|
||||
|
||||
@@ -1,15 +1,38 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe HookJob, type: :job do
|
||||
subject(:job) { described_class.perform_later(hook, message) }
|
||||
subject(:job) { described_class.perform_later(hook, event_name, event_data) }
|
||||
|
||||
let(:account) { create(:account) }
|
||||
let(:hook) { create(:integrations_hook, account: account) }
|
||||
let(:message) { create(:message) }
|
||||
let(:event_name) { 'message.created' }
|
||||
let(:event_data) { { message: create(:message, account: account) } }
|
||||
|
||||
it 'queues the job' do
|
||||
it 'enqueues the job' do
|
||||
expect { job }.to have_enqueued_job(described_class)
|
||||
.with(hook, message)
|
||||
.with(hook, event_name, event_data)
|
||||
.on_queue('integrations')
|
||||
end
|
||||
|
||||
context 'when handleable events like message.created' do
|
||||
let(:process_service) { double }
|
||||
|
||||
before do
|
||||
allow(process_service).to receive(:perform)
|
||||
end
|
||||
|
||||
it 'calls Integrations::Slack::SendOnSlackService when its a slack hook' do
|
||||
hook = create(:integrations_hook, app_id: 'slack', account: account)
|
||||
allow(Integrations::Slack::SendOnSlackService).to receive(:new).and_return(process_service)
|
||||
expect(Integrations::Slack::SendOnSlackService).to receive(:new)
|
||||
described_class.perform_now(hook, event_name, event_data)
|
||||
end
|
||||
|
||||
it 'calls Integrations::Dialogflow::ProcessorService when its a dialogflow intergation' do
|
||||
hook = create(:integrations_hook, app_id: 'dialogflow', account: account)
|
||||
allow(Integrations::Dialogflow::ProcessorService).to receive(:new).and_return(process_service)
|
||||
expect(Integrations::Dialogflow::ProcessorService).to receive(:new)
|
||||
described_class.perform_now(hook, event_name, event_data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
73
spec/lib/integrations/dialogflow/processor_service_spec.rb
Normal file
73
spec/lib/integrations/dialogflow/processor_service_spec.rb
Normal file
@@ -0,0 +1,73 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Integrations::Dialogflow::ProcessorService do
|
||||
let(:account) { create(:account) }
|
||||
let(:hook) { create(:integrations_hook, app_id: 'dialogflow', account: account) }
|
||||
let(:conversation) { create(:conversation, account: account, status: :bot) }
|
||||
let(:message) { create(:message, account: account, conversation: conversation) }
|
||||
let(:event_name) { 'message.created' }
|
||||
let(:event_data) { { message: message } }
|
||||
|
||||
describe '#perform' do
|
||||
let(:dialogflow_service) { double }
|
||||
let(:dialogflow_response) do
|
||||
ActiveSupport::HashWithIndifferentAccess.new(
|
||||
fulfillment_text: 'hello'
|
||||
)
|
||||
end
|
||||
|
||||
let(:processor) { described_class.new(event_name: event_name, hook: hook, event_data: event_data) }
|
||||
|
||||
before do
|
||||
allow(dialogflow_service).to receive(:query_result).and_return(dialogflow_response)
|
||||
allow(processor).to receive(:get_dialogflow_response).and_return(dialogflow_service)
|
||||
end
|
||||
|
||||
context 'when valid message and dialogflow returns fullfillment text' do
|
||||
it 'creates the response message' do
|
||||
expect(processor.perform.content).to eql('hello')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when dialogflow returns fullfillment text to be empty' do
|
||||
let(:dialogflow_response) do
|
||||
ActiveSupport::HashWithIndifferentAccess.new(
|
||||
fulfillment_messages: [{ payload: { content: 'hello payload' } }]
|
||||
)
|
||||
end
|
||||
|
||||
it 'creates the response message based on fulfillment messages' do
|
||||
expect(processor.perform.content).to eql('hello payload')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when dialogflow returns action' do
|
||||
let(:dialogflow_response) do
|
||||
ActiveSupport::HashWithIndifferentAccess.new(
|
||||
fulfillment_messages: [{ payload: { action: 'handoff' } }]
|
||||
)
|
||||
end
|
||||
|
||||
it 'handsoff the conversation to agent' do
|
||||
processor.perform
|
||||
expect(conversation.status).to eql('open')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when conversation is not bot' do
|
||||
let(:conversation) { create(:conversation, account: account, status: :open) }
|
||||
|
||||
it 'returns nil' do
|
||||
expect(processor.perform).to be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is private' do
|
||||
let(:message) { create(:message, account: account, conversation: conversation, private: true) }
|
||||
|
||||
it 'returns nil' do
|
||||
expect(processor.perform).to be(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,7 +12,7 @@ describe HookListener do
|
||||
let!(:event) { Events::Base.new(event_name, Time.zone.now, message: message) }
|
||||
|
||||
describe '#message_created' do
|
||||
let(:event_name) { :'conversation.created' }
|
||||
let(:event_name) { 'message.created' }
|
||||
|
||||
context 'when hook is not configured' do
|
||||
it 'does not trigger hook job' do
|
||||
@@ -24,9 +24,28 @@ describe HookListener do
|
||||
context 'when hook is configured' do
|
||||
it 'triggers hook job' do
|
||||
hook = create(:integrations_hook, account: account)
|
||||
expect(HookJob).to receive(:perform_later).with(hook, message).once
|
||||
expect(HookJob).to receive(:perform_later).with(hook, 'message.created', message: message).once
|
||||
listener.message_created(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#message_updated' do
|
||||
let(:event_name) { 'message.updated' }
|
||||
|
||||
context 'when hook is not configured' do
|
||||
it 'does not trigger hook job' do
|
||||
expect(HookJob).to receive(:perform_later).exactly(0).times
|
||||
listener.message_updated(event)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when hook is configured' do
|
||||
it 'triggers hook job' do
|
||||
hook = create(:integrations_hook, account: account)
|
||||
expect(HookJob).to receive(:perform_later).with(hook, 'message.updated', message: message).once
|
||||
listener.message_updated(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -350,6 +350,15 @@ RSpec.describe Conversation, type: :model do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#botintegration: when conversation created in inbox with dialogflow integration' do
|
||||
let(:hook) { create(:integrations_hook, app_id: 'dialogflow') }
|
||||
let(:conversation) { create(:conversation, inbox: hook.inbox) }
|
||||
|
||||
it 'returns conversation status as bot' do
|
||||
expect(conversation.status).to eq('bot')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#can_reply?' do
|
||||
describe 'on channels without 24 hour restriction' do
|
||||
let(:conversation) { create(:conversation) }
|
||||
|
||||
Reference in New Issue
Block a user