248 lines
10 KiB
Ruby
248 lines
10 KiB
Ruby
require 'rails_helper'
|
|
|
|
RSpec.describe 'Conversations API', type: :request do
|
|
let(:account) { create(:account) }
|
|
let(:administrator) { create(:user, account: account, role: :administrator) }
|
|
|
|
describe 'GET /api/v1/accounts/{account.id}/conversations/:id' do
|
|
it 'returns SLA data for the conversation if the feature is enabled' do
|
|
account.enable_features!('sla')
|
|
conversation = create(:conversation, account: account)
|
|
applied_sla = create(:applied_sla, conversation: conversation)
|
|
sla_event = create(:sla_event, conversation: conversation, applied_sla: applied_sla)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}", headers: administrator.create_new_auth_token
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body['applied_sla']['id']).to eq(applied_sla.id)
|
|
expect(response.parsed_body['sla_events'].first['id']).to eq(sla_event.id)
|
|
end
|
|
|
|
it 'does not return SLA data for the conversation if the feature is disabled' do
|
|
account.disable_features!('sla')
|
|
conversation = create(:conversation, account: account)
|
|
create(:applied_sla, conversation: conversation)
|
|
create(:sla_event, conversation: conversation)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}", headers: administrator.create_new_auth_token
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body.keys).not_to include('applied_sla')
|
|
expect(response.parsed_body.keys).not_to include('sla_events')
|
|
end
|
|
|
|
context 'when agent has team access' do
|
|
let(:agent) { create(:user, account: account, role: :agent) }
|
|
let(:team) { create(:team, account: account) }
|
|
let(:conversation) { create(:conversation, account: account, team: team) }
|
|
|
|
before do
|
|
create(:team_member, team: team, user: agent)
|
|
end
|
|
|
|
it 'allows accessing the conversation via team membership' do
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}", headers: agent.create_new_auth_token
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body['id']).to eq(conversation.display_id)
|
|
end
|
|
end
|
|
|
|
context 'when agent has a custom role' do
|
|
let(:agent) { create(:user, account: account, role: :agent) }
|
|
let(:conversation) { create(:conversation, account: account) }
|
|
|
|
before do
|
|
create(:inbox_member, user: agent, inbox: conversation.inbox)
|
|
end
|
|
|
|
it 'returns unauthorized for unassigned conversation without permission' do
|
|
custom_role = create(:custom_role, account: account, permissions: ['conversation_participating_manage'])
|
|
account.account_users.find_by(user_id: agent.id).update!(custom_role: custom_role)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}", headers: agent.create_new_auth_token
|
|
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
|
|
it 'returns the conversation when permission allows managing unassigned conversations, including when assigned to agent' do
|
|
custom_role = create(:custom_role, account: account, permissions: ['conversation_unassigned_manage'])
|
|
account_user = account.account_users.find_by(user_id: agent.id)
|
|
account_user.update!(custom_role: custom_role)
|
|
conversation.update!(assignee: agent)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}", headers: agent.create_new_auth_token
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body['id']).to eq(conversation.display_id)
|
|
end
|
|
|
|
it 'returns the conversation when permission allows managing assigned conversations' do
|
|
custom_role = create(:custom_role, account: account, permissions: ['conversation_participating_manage'])
|
|
account_user = account.account_users.find_by(user_id: agent.id)
|
|
account_user.update!(custom_role: custom_role)
|
|
conversation.update!(assignee: agent)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}", headers: agent.create_new_auth_token
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body['id']).to eq(conversation.display_id)
|
|
end
|
|
|
|
it 'returns the conversation when permission allows managing participating conversations' do
|
|
custom_role = create(:custom_role, account: account, permissions: ['conversation_participating_manage'])
|
|
account_user = account.account_users.find_by(user_id: agent.id)
|
|
account_user.update!(custom_role: custom_role)
|
|
create(:conversation_participant, conversation: conversation, account: account, user: agent)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}", headers: agent.create_new_auth_token
|
|
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.parsed_body['id']).to eq(conversation.display_id)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'GET /api/v1/accounts/{account.id}/conversations/:id/reporting_events' do
|
|
let(:conversation) { create(:conversation, account: account) }
|
|
let(:inbox) { conversation.inbox }
|
|
let(:agent) { administrator }
|
|
|
|
before do
|
|
# Create reporting events for this conversation
|
|
@event1 = create(:reporting_event,
|
|
account: account,
|
|
conversation: conversation,
|
|
inbox: inbox,
|
|
user: agent,
|
|
name: 'first_response',
|
|
value: 120,
|
|
created_at: 3.hours.ago)
|
|
|
|
@event2 = create(:reporting_event,
|
|
account: account,
|
|
conversation: conversation,
|
|
inbox: inbox,
|
|
user: agent,
|
|
name: 'reply_time',
|
|
value: 45,
|
|
created_at: 2.hours.ago)
|
|
|
|
@event3 = create(:reporting_event,
|
|
account: account,
|
|
conversation: conversation,
|
|
inbox: inbox,
|
|
user: agent,
|
|
name: 'resolution',
|
|
value: 300,
|
|
created_at: 1.hour.ago)
|
|
|
|
# Create an event for a different conversation (should not be included)
|
|
other_conversation = create(:conversation, account: account)
|
|
create(:reporting_event,
|
|
account: account,
|
|
conversation: other_conversation,
|
|
inbox: other_conversation.inbox,
|
|
user: agent,
|
|
name: 'other_conversation_event',
|
|
value: 60)
|
|
end
|
|
|
|
context 'when it is an unauthenticated user' do
|
|
it 'returns unauthorized' do
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
end
|
|
|
|
context 'when it is an authenticated user with conversation access' do
|
|
it 'returns all reporting events for the conversation' do
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
|
|
headers: administrator.create_new_auth_token,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
json_response = response.parsed_body
|
|
|
|
# Should return array directly (no pagination)
|
|
expect(json_response).to be_an(Array)
|
|
expect(json_response.size).to eq(3)
|
|
|
|
# Check they are sorted by created_at asc (oldest first)
|
|
expect(json_response.first['name']).to eq('first_response')
|
|
expect(json_response.last['name']).to eq('resolution')
|
|
|
|
# Verify it doesn't include events from other conversations
|
|
event_names = json_response.map { |e| e['name'] }
|
|
expect(event_names).not_to include('other_conversation_event')
|
|
end
|
|
|
|
it 'returns empty array when conversation has no reporting events' do
|
|
conversation_without_events = create(:conversation, account: account)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation_without_events.display_id}/reporting_events",
|
|
headers: administrator.create_new_auth_token,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
json_response = response.parsed_body
|
|
|
|
expect(json_response).to be_an(Array)
|
|
expect(json_response).to be_empty
|
|
end
|
|
end
|
|
|
|
context 'when agent has limited access' do
|
|
let(:limited_agent) { create(:user, account: account, role: :agent) }
|
|
|
|
it 'returns unauthorized for unassigned conversation without permission' do
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
|
|
headers: limited_agent.create_new_auth_token,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
|
|
it 'returns reporting events when agent is assigned to the conversation' do
|
|
conversation.update!(assignee: limited_agent)
|
|
# Also create inbox member for the agent
|
|
create(:inbox_member, user: limited_agent, inbox: conversation.inbox)
|
|
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
|
|
headers: limited_agent.create_new_auth_token,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
json_response = response.parsed_body
|
|
|
|
expect(json_response).to be_an(Array)
|
|
expect(json_response.size).to eq(3)
|
|
end
|
|
end
|
|
|
|
context 'when agent has team access' do
|
|
let(:team_agent) { create(:user, account: account, role: :agent) }
|
|
let(:team) { create(:team, account: account) }
|
|
|
|
before do
|
|
create(:team_member, team: team, user: team_agent)
|
|
conversation.update!(team: team)
|
|
end
|
|
|
|
it 'allows accessing conversation reporting events via team membership' do
|
|
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
|
|
headers: team_agent.create_new_auth_token,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
json_response = response.parsed_body
|
|
|
|
expect(json_response).to be_an(Array)
|
|
expect(json_response.size).to eq(3)
|
|
end
|
|
end
|
|
end
|
|
end
|