Chatwoot/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb
Aswin Dev P.S 24e6a92297
feat: IMAP Email Channel (#3298)
This change allows the user to configure both IMAP and SMTP for an email inbox. IMAP enables the user to see emails in Chatwoot. And user can use SMTP to reply to an email conversation.

Users can use the default settings to send and receive emails for email inboxes if both IMAP and SMTP are disabled.

Fixes #2520
2021-11-19 11:52:27 +05:30

557 lines
20 KiB
Ruby

require 'rails_helper'
RSpec.describe 'Inboxes API', type: :request do
let(:account) { create(:account) }
let(:agent) { create(:user, account: account, role: :agent) }
let(:admin) { create(:user, account: account, role: :administrator) }
describe 'GET /api/v1/accounts/{account.id}/inboxes' do
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/inboxes"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:agent) { create(:user, account: account, role: :agent) }
let(:admin) { create(:user, account: account, role: :administrator) }
let(:inbox) { create(:inbox, account: account) }
before do
create(:inbox, account: account)
create(:inbox_member, user: agent, inbox: inbox)
end
it 'returns all inboxes of current_account as administrator' do
get "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
expect(JSON.parse(response.body, symbolize_names: true)[:payload].size).to eq(2)
end
it 'returns only assigned inboxes of current_account as agent' do
get "/api/v1/accounts/#{account.id}/inboxes",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
expect(JSON.parse(response.body, symbolize_names: true)[:payload].size).to eq(1)
end
end
end
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}' do
let(:inbox) { create(:inbox, account: account) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:agent) { create(:user, account: account, role: :agent) }
let(:admin) { create(:user, account: account, role: :administrator) }
let(:inbox) { create(:inbox, account: account) }
it 'returns unauthorized for an agent who is not assigned' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
it 'returns the inbox if administrator' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
expect(JSON.parse(response.body, symbolize_names: true)[:id]).to eq(inbox.id)
end
it 'returns the inbox if assigned inbox is assigned as agent' do
create(:inbox_member, user: agent, inbox: inbox)
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
expect(JSON.parse(response.body, symbolize_names: true)[:id]).to eq(inbox.id)
end
end
end
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/assignable_agents' do
let(:inbox) { create(:inbox, account: account) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/assignable_agents"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
before do
create(:inbox_member, user: agent, inbox: inbox)
end
it 'returns all assignable inbox members along with administrators' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/assignable_agents",
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
response_data = JSON.parse(response.body, symbolize_names: true)[:payload]
expect(response_data.size).to eq(2)
expect(response_data.pluck(:role)).to include('agent', 'administrator')
end
end
end
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/campaigns' do
let(:inbox) { create(:inbox, account: account) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:agent) { create(:user, account: account, role: :agent) }
let(:administrator) { create(:user, account: account, role: :administrator) }
let!(:campaign) { create(:campaign, account: account, inbox: inbox) }
it 'returns unauthorized for agents' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
it 'returns all campaigns belonging to the inbox to administrators' do
# create a random campaign
create(:campaign, account: account)
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/campaigns",
headers: administrator.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
body = JSON.parse(response.body, symbolize_names: true)
expect(body.first[:id]).to eq(campaign.display_id)
expect(body.length).to eq(1)
end
end
end
describe 'DELETE /api/v1/accounts/{account.id}/inboxes/{inbox.id}/avatar' do
let(:inbox) { create(:inbox, account: account) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/avatar"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
before do
create(:inbox_member, user: agent, inbox: inbox)
inbox.avatar.attach(io: File.open(Rails.root.join('spec/assets/avatar.png')), filename: 'avatar.png', content_type: 'image/png')
end
it 'delete inbox avatar for administrator user' do
delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/avatar",
headers: admin.create_new_auth_token,
as: :json
expect { inbox.avatar.attachment.reload }.to raise_error(ActiveRecord::RecordNotFound)
expect(response).to have_http_status(:success)
end
it 'returns unauthorized for agent user' do
delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/avatar",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
end
end
describe 'DELETE /api/v1/accounts/{account.id}/inboxes/:id' do
let(:inbox) { create(:inbox, account: account) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:admin) { create(:user, account: account, role: :administrator) }
it 'deletes inbox' do
delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
expect { inbox.reload }.to raise_exception(ActiveRecord::RecordNotFound)
end
it 'is unable to delete inbox of another account' do
other_account = create(:account)
other_inbox = create(:inbox, account: other_account)
delete "/api/v1/accounts/#{account.id}/inboxes/#{other_inbox.id}",
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:not_found)
end
it 'is unable to delete inbox as agent' do
agent = create(:user, account: account, role: :agent)
delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
end
end
describe 'POST /api/v1/accounts/{account.id}/inboxes' do
let(:inbox) { create(:inbox, account: account) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
post "/api/v1/accounts/#{account.id}/inboxes"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:admin) { create(:user, account: account, role: :administrator) }
let(:valid_params) { { name: 'test', channel: { type: 'web_widget', website_url: 'test.com' } } }
it 'will not create inbox for agent' do
agent = create(:user, account: account, role: :agent)
post "/api/v1/accounts/#{account.id}/inboxes",
headers: agent.create_new_auth_token,
params: valid_params,
as: :json
expect(response).to have_http_status(:unauthorized)
end
it 'creates a webwidget inbox when administrator' do
post "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
params: valid_params,
as: :json
expect(response).to have_http_status(:success)
expect(response.body).to include('test.com')
end
it 'creates a email inbox when administrator' do
post "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
params: { name: 'test', channel: { type: 'email', email: 'test@test.com' } },
as: :json
expect(response).to have_http_status(:success)
expect(response.body).to include('test@test.com')
end
it 'creates an api inbox when administrator' do
post "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
params: { name: 'API Inbox', channel: { type: 'api', webhook_url: 'http://test.com' } },
as: :json
expect(response).to have_http_status(:success)
expect(response.body).to include('API Inbox')
end
it 'creates a line inbox when administrator' do
post "/api/v1/accounts/#{account.id}/inboxes",
headers: admin.create_new_auth_token,
params: { name: 'Line Inbox',
channel: { type: 'line', line_channel_id: SecureRandom.uuid, line_channel_secret: SecureRandom.uuid,
line_channel_token: SecureRandom.uuid } },
as: :json
expect(response).to have_http_status(:success)
expect(response.body).to include('Line Inbox')
expect(response.body).to include('callback_webhook_url')
end
end
end
describe 'PATCH /api/v1/accounts/{account.id}/inboxes/:id' do
let(:inbox) { create(:inbox, account: account) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:admin) { create(:user, account: account, role: :administrator) }
let(:valid_params) { { name: 'new test inbox', enable_auto_assignment: false } }
it 'will not update inbox for agent' do
agent = create(:user, account: account, role: :agent)
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: agent.create_new_auth_token,
params: valid_params,
as: :json
expect(response).to have_http_status(:unauthorized)
end
it 'updates inbox when administrator' do
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
headers: admin.create_new_auth_token,
params: valid_params,
as: :json
expect(response).to have_http_status(:success)
expect(inbox.reload.enable_auto_assignment).to be_falsey
expect(JSON.parse(response.body)['name']).to eq 'new test inbox'
end
it 'updates api inbox when administrator' do
api_channel = create(:channel_api, account: account)
api_inbox = create(:inbox, channel: api_channel, account: account)
patch "/api/v1/accounts/#{account.id}/inboxes/#{api_inbox.id}",
headers: admin.create_new_auth_token,
params: { enable_auto_assignment: false, channel: { webhook_url: 'webhook.test', selected_feature_flags: [] } },
as: :json
expect(response).to have_http_status(:success)
expect(api_inbox.reload.enable_auto_assignment).to be_falsey
expect(api_channel.reload.webhook_url).to eq('webhook.test')
end
it 'updates email inbox when administrator' do
email_channel = create(:channel_email, account: account)
email_inbox = create(:inbox, channel: email_channel, account: account)
patch "/api/v1/accounts/#{account.id}/inboxes/#{email_inbox.id}",
headers: admin.create_new_auth_token,
params: { enable_auto_assignment: false, channel: { email: 'emailtest@email.test' } },
as: :json
expect(response).to have_http_status(:success)
expect(email_inbox.reload.enable_auto_assignment).to be_falsey
expect(email_channel.reload.email).to eq('emailtest@email.test')
end
it 'updates email inbox with imap when administrator' do
email_channel = create(:channel_email, account: account)
email_inbox = create(:inbox, channel: email_channel, account: account)
imap_connection = double
allow(Mail).to receive(:connection).and_return(imap_connection)
patch "/api/v1/accounts/#{account.id}/inboxes/#{email_inbox.id}",
headers: admin.create_new_auth_token,
params: {
channel: {
imap_enabled: true,
imap_address: 'imap.gmail.com',
imap_port: 993,
imap_email: 'imaptest@gmail.com'
}
},
as: :json
expect(response).to have_http_status(:success)
expect(email_channel.reload.imap_enabled).to be true
expect(email_channel.reload.imap_address).to eq('imap.gmail.com')
expect(email_channel.reload.imap_port).to eq(993)
end
it 'updates email inbox with smtp when administrator' do
email_channel = create(:channel_email, account: account)
email_inbox = create(:inbox, channel: email_channel, account: account)
smtp_connection = double
allow(smtp_connection).to receive(:finish).and_return(true)
allow(Net::SMTP).to receive(:start).and_return(smtp_connection)
patch "/api/v1/accounts/#{account.id}/inboxes/#{email_inbox.id}",
headers: admin.create_new_auth_token,
params: {
channel: {
smtp_enabled: true,
smtp_address: 'smtp.gmail.com',
smtp_port: 587,
smtp_email: 'smtptest@gmail.com'
}
},
as: :json
expect(response).to have_http_status(:success)
expect(email_channel.reload.smtp_enabled).to be true
expect(email_channel.reload.smtp_address).to eq('smtp.gmail.com')
expect(email_channel.reload.smtp_port).to eq(587)
end
it 'updates avatar when administrator' do
# no avatar before upload
expect(inbox.avatar.attached?).to eq(false)
file = fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png')
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
params: valid_params.merge(avatar: file),
headers: admin.create_new_auth_token
expect(response).to have_http_status(:success)
inbox.reload
expect(inbox.avatar.attached?).to eq(true)
end
it 'updates working hours when administrator' do
params = {
working_hours: [{ 'day_of_week' => 0, 'open_hour' => 9, 'open_minutes' => 0, 'close_hour' => 17, 'close_minutes' => 0 }],
working_hours_enabled: true,
out_of_office_message: 'hello'
}
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
params: valid_params.merge(params),
headers: admin.create_new_auth_token
expect(response).to have_http_status(:success)
inbox.reload
expect(inbox.reload.weekly_schedule.find { |schedule| schedule['day_of_week'] == 0 }['open_hour']).to eq 9
end
end
end
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/agent_bot' do
let(:inbox) { create(:inbox, account: account) }
before do
create(:inbox_member, user: agent, inbox: inbox)
end
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/agent_bot"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
it 'returns empty when no agent bot is present' do
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/agent_bot",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
inbox_data = JSON.parse(response.body, symbolize_names: true)
expect(inbox_data[:agent_bot].blank?).to eq(true)
end
it 'returns the agent bot attached to the inbox' do
agent_bot = create(:agent_bot)
create(:agent_bot_inbox, agent_bot: agent_bot, inbox: inbox)
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/agent_bot",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
inbox_data = JSON.parse(response.body, symbolize_names: true)
expect(inbox_data[:agent_bot][:name]).to eq agent_bot.name
end
end
end
describe 'POST /api/v1/accounts/{account.id}/inboxes/:id/set_agent_bot' do
let(:inbox) { create(:inbox, account: account) }
let(:agent_bot) { create(:agent_bot) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/set_agent_bot"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:admin) { create(:user, account: account, role: :administrator) }
let(:valid_params) { { agent_bot: agent_bot.id } }
it 'sets the agent bot' do
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/set_agent_bot",
headers: admin.create_new_auth_token,
params: valid_params,
as: :json
expect(response).to have_http_status(:success)
expect(inbox.reload.agent_bot.id).to eq agent_bot.id
end
it 'throw error when invalid agent bot id' do
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/set_agent_bot",
headers: admin.create_new_auth_token,
params: { agent_bot: 0 },
as: :json
expect(response).to have_http_status(:not_found)
end
it 'disconnects the agent bot' do
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/set_agent_bot",
headers: admin.create_new_auth_token,
params: { agent_bot: nil },
as: :json
expect(response).to have_http_status(:success)
expect(inbox.reload.agent_bot).to be_falsey
end
it 'will not update agent bot when its an agent' do
agent = create(:user, account: account, role: :agent)
post "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/set_agent_bot",
headers: agent.create_new_auth_token,
params: valid_params,
as: :json
expect(response).to have_http_status(:unauthorized)
end
end
end
end