Merge branch 'develop' into chore/update-rails
# Conflicts: # Gemfile.lock # package.json # pnpm-lock.yaml
This commit is contained in:
@@ -563,8 +563,11 @@ RSpec.describe 'Contacts API', type: :request do
|
||||
|
||||
describe 'PATCH /api/v1/accounts/{account.id}/contacts/:id' do
|
||||
let(:custom_attributes) { { test: 'test', test1: 'test1' } }
|
||||
let!(:contact) { create(:contact, account: account, custom_attributes: custom_attributes) }
|
||||
let(:valid_params) { { name: 'Test Blub', custom_attributes: { test: 'new test', test2: 'test2' } } }
|
||||
let(:additional_attributes) { { attr1: 'attr1', attr2: 'attr2' } }
|
||||
let!(:contact) { create(:contact, account: account, custom_attributes: custom_attributes, additional_attributes: additional_attributes) }
|
||||
let(:valid_params) do
|
||||
{ name: 'Test Blub', custom_attributes: { test: 'new test', test2: 'test2' }, additional_attributes: { attr2: 'new attr2', attr3: 'attr3' } }
|
||||
end
|
||||
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
@@ -588,6 +591,7 @@ RSpec.describe 'Contacts API', type: :request do
|
||||
expect(contact.reload.name).to eq('Test Blub')
|
||||
# custom attributes are merged properly without overwriting existing ones
|
||||
expect(contact.custom_attributes).to eq({ 'test' => 'new test', 'test1' => 'test1', 'test2' => 'test2' })
|
||||
expect(contact.additional_attributes).to eq({ 'attr1' => 'attr1', 'attr2' => 'new attr2', 'attr3' => 'attr3' })
|
||||
end
|
||||
|
||||
it 'prevents the update of contact of another account' do
|
||||
|
||||
@@ -84,7 +84,6 @@ RSpec.describe 'Conversation Messages API', type: :request do
|
||||
context 'when api inbox' do
|
||||
let(:api_channel) { create(:channel_api, account: account) }
|
||||
let(:api_inbox) { create(:inbox, channel: api_channel, account: account) }
|
||||
let(:inbox_member) { create(:inbox_member, user: agent, inbox: api_inbox) }
|
||||
let(:conversation) { create(:conversation, inbox: api_inbox, account: account) }
|
||||
|
||||
it 'reopens the conversation with new incoming message' do
|
||||
@@ -294,4 +293,67 @@ RSpec.describe 'Conversation Messages API', type: :request do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH /api/v1/accounts/{account.id}/conversations/:conversation_id/messages/:id' do
|
||||
let(:api_channel) { create(:channel_api, account: account) }
|
||||
let(:api_inbox) { create(:inbox, channel: api_channel, account: account) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let!(:conversation) { create(:conversation, inbox: api_inbox, account: account) }
|
||||
let!(:message) { create(:message, conversation: conversation, account: account, status: :sent) }
|
||||
|
||||
context 'when unauthenticated' do
|
||||
it 'returns unauthorized' do
|
||||
patch api_v1_account_conversation_message_url(account_id: account.id, conversation_id: conversation.display_id, id: message.id)
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated agent' do
|
||||
context 'when agent has non-API inbox' do
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let!(:conversation) { create(:conversation, inbox: inbox, account: account) }
|
||||
|
||||
before { create(:inbox_member, inbox: inbox, user: agent) }
|
||||
|
||||
it 'returns forbidden' do
|
||||
patch api_v1_account_conversation_message_url(
|
||||
account_id: account.id,
|
||||
conversation_id: conversation.display_id,
|
||||
id: message.id
|
||||
), params: { status: 'failed', external_error: 'err' }, headers: agent.create_new_auth_token, as: :json
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when agent has API inbox' do
|
||||
before { create(:inbox_member, inbox: api_inbox, user: agent) }
|
||||
|
||||
it 'uses StatusUpdateService to perform status update' do
|
||||
service = instance_double(Messages::StatusUpdateService)
|
||||
expect(Messages::StatusUpdateService).to receive(:new)
|
||||
.with(message, 'failed', 'err123')
|
||||
.and_return(service)
|
||||
expect(service).to receive(:perform)
|
||||
patch api_v1_account_conversation_message_url(
|
||||
account_id: account.id,
|
||||
conversation_id: conversation.display_id,
|
||||
id: message.id
|
||||
), params: { status: 'failed', external_error: 'err123' }, headers: agent.create_new_auth_token, as: :json
|
||||
end
|
||||
|
||||
it 'updates status to failed with external_error' do
|
||||
patch api_v1_account_conversation_message_url(
|
||||
account_id: account.id,
|
||||
conversation_id: conversation.display_id,
|
||||
id: message.id
|
||||
), params: { status: 'failed', external_error: 'err123' }, headers: agent.create_new_auth_token, as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(message.reload.status).to eq('failed')
|
||||
expect(message.reload.external_error).to eq('err123')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -843,7 +843,7 @@ RSpec.describe 'Conversations API', type: :request do
|
||||
create(:inbox_member, user: agent, inbox: conversation.inbox)
|
||||
end
|
||||
|
||||
it 'updates last seen' do
|
||||
it 'updates custom attributes' do
|
||||
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/custom_attributes",
|
||||
headers: agent.create_new_auth_token,
|
||||
params: valid_params,
|
||||
@@ -854,6 +854,27 @@ RSpec.describe 'Conversations API', type: :request do
|
||||
expect(conversation.reload.custom_attributes.count).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is a bot' do
|
||||
let(:agent_bot) { create(:agent_bot, account: account) }
|
||||
let(:custom_attributes) { { bot_id: 1001, flow_name: 'support_flow', step: 'greeting' } }
|
||||
let(:valid_params) { { custom_attributes: custom_attributes } }
|
||||
|
||||
before do
|
||||
create(:agent_bot_inbox, agent_bot: agent_bot, inbox: conversation.inbox)
|
||||
end
|
||||
|
||||
it 'updates custom attributes' do
|
||||
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/custom_attributes",
|
||||
headers: { api_access_token: agent_bot.access_token.token },
|
||||
params: valid_params,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(conversation.reload.custom_attributes).not_to be_nil
|
||||
expect(conversation.reload.custom_attributes.count).to eq 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/conversations/:id/attachments' do
|
||||
|
||||
@@ -147,6 +147,32 @@ RSpec.describe 'Inboxes API', type: :request do
|
||||
expect(data[:imap_login]).to eq('test@test.com')
|
||||
end
|
||||
|
||||
context 'when it is a Twilio inbox' do
|
||||
let(:twilio_channel) { create(:channel_twilio_sms, account: account, account_sid: 'AC123', auth_token: 'secrettoken') }
|
||||
let(:twilio_inbox) { create(:inbox, channel: twilio_channel, account: account) }
|
||||
|
||||
it 'returns auth_token and account_sid for admin' do
|
||||
get "/api/v1/accounts/#{account.id}/inboxes/#{twilio_inbox.id}",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:success)
|
||||
data = JSON.parse(response.body, symbolize_names: true)
|
||||
expect(data[:auth_token]).to eq('secrettoken')
|
||||
expect(data[:account_sid]).to eq('AC123')
|
||||
end
|
||||
|
||||
it "doesn't return auth_token and account_sid for agent" do
|
||||
create(:inbox_member, user: agent, inbox: twilio_inbox)
|
||||
get "/api/v1/accounts/#{account.id}/inboxes/#{twilio_inbox.id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:success)
|
||||
data = JSON.parse(response.body, symbolize_names: true)
|
||||
expect(data[:auth_token]).to be_nil
|
||||
expect(data[:account_sid]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'fetch API inbox without hmac token when agent' do
|
||||
api_channel = create(:channel_api, account: account)
|
||||
api_inbox = create(:inbox, channel: api_channel, account: account)
|
||||
@@ -518,6 +544,22 @@ RSpec.describe 'Inboxes API', type: :request do
|
||||
expect(email_channel.reload.email).to eq('emailtest@email.test')
|
||||
end
|
||||
|
||||
it 'updates twilio sms inbox when administrator' do
|
||||
twilio_sms_channel = create(:channel_twilio_sms, account: account)
|
||||
twilio_sms_inbox = create(:inbox, channel: twilio_sms_channel, account: account)
|
||||
expect(twilio_sms_inbox.reload.channel.account_sid).not_to eq('account_sid')
|
||||
expect(twilio_sms_inbox.reload.channel.auth_token).not_to eq('new_auth_token')
|
||||
|
||||
patch "/api/v1/accounts/#{account.id}/inboxes/#{twilio_sms_inbox.id}",
|
||||
headers: admin.create_new_auth_token,
|
||||
params: { channel: { account_sid: 'account_sid', auth_token: 'new_auth_token' } },
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(twilio_sms_inbox.reload.channel.account_sid).to eq('account_sid')
|
||||
expect(twilio_sms_inbox.reload.channel.auth_token).to eq('new_auth_token')
|
||||
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)
|
||||
@@ -675,6 +717,94 @@ RSpec.describe 'Inboxes API', type: :request do
|
||||
expect(email_channel.reload.smtp_authentication).to eq('plain')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when handling CSAT configuration' do
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
let(:csat_config) do
|
||||
{
|
||||
'display_type' => 'emoji',
|
||||
'message' => 'How would you rate your experience?',
|
||||
'survey_rules' => {
|
||||
'operator' => 'contains',
|
||||
'values' => %w[support help]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'successfully updates the inbox with CSAT configuration' do
|
||||
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
|
||||
params: {
|
||||
csat_survey_enabled: true,
|
||||
csat_config: csat_config
|
||||
},
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
context 'when CSAT is configured' do
|
||||
before do
|
||||
patch "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
|
||||
params: {
|
||||
csat_survey_enabled: true,
|
||||
csat_config: csat_config
|
||||
},
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end
|
||||
|
||||
it 'returns configured CSAT settings in inbox details' 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)
|
||||
json_response = response.parsed_body
|
||||
expect(json_response['csat_survey_enabled']).to be true
|
||||
|
||||
saved_config = json_response['csat_config']
|
||||
expect(saved_config).to be_present
|
||||
expect(saved_config['display_type']).to eq('emoji')
|
||||
end
|
||||
|
||||
it 'returns configured CSAT message' do
|
||||
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
json_response = response.parsed_body
|
||||
saved_config = json_response['csat_config']
|
||||
expect(saved_config['message']).to eq('How would you rate your experience?')
|
||||
end
|
||||
|
||||
it 'returns configured CSAT survey rules' do
|
||||
get "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
json_response = response.parsed_body
|
||||
saved_config = json_response['csat_config']
|
||||
expect(saved_config['survey_rules']['operator']).to eq('contains')
|
||||
expect(saved_config['survey_rules']['values']).to match_array(%w[support help])
|
||||
end
|
||||
|
||||
it 'includes CSAT configuration in inbox list' do
|
||||
get "/api/v1/accounts/#{account.id}/inboxes",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
inbox_list = response.parsed_body
|
||||
found_inbox = inbox_list['payload'].find { |i| i['id'] == inbox.id }
|
||||
|
||||
expect(found_inbox['csat_survey_enabled']).to be true
|
||||
expect(found_inbox['csat_config']).to be_present
|
||||
expect(found_inbox['csat_config']['display_type']).to eq('emoji')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/agent_bot' do
|
||||
|
||||
@@ -100,6 +100,7 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
description: 'This is a sample issue.',
|
||||
assignee_id: 'user1',
|
||||
priority: 'high',
|
||||
state_id: 'state1',
|
||||
label_ids: ['label1']
|
||||
}
|
||||
end
|
||||
|
||||
@@ -119,7 +119,7 @@ RSpec.describe 'Accounts API', type: :request do
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
it 'shows an account' do
|
||||
account.update(auto_resolve_duration: 30)
|
||||
account.update(name: 'new name')
|
||||
|
||||
get "/api/v1/accounts/#{account.id}",
|
||||
headers: admin.create_new_auth_token,
|
||||
@@ -130,7 +130,6 @@ RSpec.describe 'Accounts API', type: :request do
|
||||
expect(response.body).to include(account.locale)
|
||||
expect(response.body).to include(account.domain)
|
||||
expect(response.body).to include(account.support_email)
|
||||
expect(response.body).to include(account.auto_resolve_duration.to_s)
|
||||
expect(response.body).to include(account.locale)
|
||||
end
|
||||
end
|
||||
@@ -189,7 +188,9 @@ RSpec.describe 'Accounts API', type: :request do
|
||||
locale: 'en',
|
||||
domain: 'example.com',
|
||||
support_email: 'care@example.com',
|
||||
auto_resolve_duration: 40,
|
||||
auto_resolve_after: 40,
|
||||
auto_resolve_message: 'Auto resolved',
|
||||
auto_resolve_ignore_waiting: false,
|
||||
timezone: 'Asia/Kolkata',
|
||||
industry: 'Technology',
|
||||
company_size: '1-10'
|
||||
@@ -206,7 +207,10 @@ RSpec.describe 'Accounts API', type: :request do
|
||||
expect(account.reload.locale).to eq(params[:locale])
|
||||
expect(account.reload.domain).to eq(params[:domain])
|
||||
expect(account.reload.support_email).to eq(params[:support_email])
|
||||
expect(account.reload.auto_resolve_duration).to eq(params[:auto_resolve_duration])
|
||||
|
||||
%w[auto_resolve_after auto_resolve_message auto_resolve_ignore_waiting].each do |attribute|
|
||||
expect(account.reload.settings[attribute]).to eq(params[attribute.to_sym])
|
||||
end
|
||||
|
||||
%w[timezone industry company_size].each do |attribute|
|
||||
expect(account.reload.custom_attributes[attribute]).to eq(params[attribute.to_sym])
|
||||
|
||||
@@ -9,7 +9,11 @@ RSpec.describe '/api/v1/widget/campaigns', type: :request do
|
||||
describe 'GET /api/v1/widget/campaigns' do
|
||||
let(:params) { { website_token: web_widget.website_token } }
|
||||
|
||||
context 'with correct website token' do
|
||||
context 'when campaigns feature is enabled' do
|
||||
before do
|
||||
account.enable_features!('campaigns')
|
||||
end
|
||||
|
||||
it 'returns the list of enabled campaigns' do
|
||||
get '/api/v1/widget/campaigns', params: params
|
||||
|
||||
@@ -21,8 +25,22 @@ RSpec.describe '/api/v1/widget/campaigns', type: :request do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when campaigns feature is disabled' do
|
||||
before do
|
||||
account.disable_features!('campaigns')
|
||||
end
|
||||
|
||||
it 'returns empty array' do
|
||||
get '/api/v1/widget/campaigns', params: params
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
json_response = response.parsed_body
|
||||
expect(json_response).to eq []
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid website token' do
|
||||
it 'returns the list of agents' do
|
||||
it 'returns not found status' do
|
||||
get '/api/v1/widget/campaigns', params: { website_token: '' }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user