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:
Sojan Jose
2021-05-05 21:06:11 +05:30
committed by GitHub
parent fd0c26cdae
commit b30ecb27a6
19 changed files with 303 additions and 26 deletions

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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) }