Restructure omni services and add Chatwoot research snapshot
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::AssistantResponses', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
let(:document) { create(:captain_document, assistant: assistant, account: account) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:another_assistant) { create(:captain_assistant, account: account) }
|
||||
let(:another_document) { create(:captain_document, account: account, assistant: assistant) }
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/:account_id/captain/assistant_responses' do
|
||||
context 'when no filters are applied' do
|
||||
before do
|
||||
create_list(:captain_assistant_response, 30,
|
||||
account: account,
|
||||
assistant: assistant,
|
||||
documentable: document)
|
||||
end
|
||||
|
||||
it 'returns first page of responses with default pagination' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(25)
|
||||
end
|
||||
|
||||
it 'returns second page of responses' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: { page: 2 },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(5)
|
||||
expect(json_response[:meta]).to eq({ page: 2, total_count: 30 })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when filtering by assistant_id' do
|
||||
before do
|
||||
create_list(:captain_assistant_response, 3,
|
||||
account: account,
|
||||
assistant: assistant,
|
||||
documentable: document)
|
||||
create_list(:captain_assistant_response, 2,
|
||||
account: account,
|
||||
assistant: another_assistant,
|
||||
documentable: document)
|
||||
end
|
||||
|
||||
it 'returns only responses for the specified assistant' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: { assistant_id: assistant.id },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
expect(json_response[:payload][0][:assistant][:id]).to eq(assistant.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when filtering by document_id' do
|
||||
before do
|
||||
create_list(:captain_assistant_response, 3,
|
||||
account: account,
|
||||
assistant: assistant,
|
||||
documentable: document)
|
||||
create_list(:captain_assistant_response, 2,
|
||||
account: account,
|
||||
assistant: assistant,
|
||||
documentable: another_document)
|
||||
end
|
||||
|
||||
it 'returns only responses for the specified document' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: { document_id: document.id },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
expect(json_response[:payload][0][:documentable][:id]).to eq(document.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when searching' do
|
||||
before do
|
||||
create(:captain_assistant_response,
|
||||
account: account,
|
||||
assistant: assistant,
|
||||
question: 'How to reset password?',
|
||||
answer: 'Click forgot password')
|
||||
create(:captain_assistant_response,
|
||||
account: account,
|
||||
assistant: assistant,
|
||||
question: 'How to change email?',
|
||||
answer: 'Go to settings')
|
||||
end
|
||||
|
||||
it 'finds responses by question text' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: { search: 'password' },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(1)
|
||||
expect(json_response[:payload][0][:question]).to include('password')
|
||||
end
|
||||
|
||||
it 'finds responses by answer text' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: { search: 'settings' },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(1)
|
||||
expect(json_response[:payload][0][:answer]).to include('settings')
|
||||
end
|
||||
|
||||
it 'returns empty when no matches' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: { search: 'nonexistent' },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/:account_id/captain/assistant_responses/:id' do
|
||||
let!(:response_record) { create(:captain_assistant_response, assistant: assistant, account: account) }
|
||||
|
||||
it 'returns the requested response if the user is agent or admin' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistant_responses/#{response_record.id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:id]).to eq(response_record.id)
|
||||
expect(json_response[:question]).to eq(response_record.question)
|
||||
expect(json_response[:answer]).to eq(response_record.answer)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/:account_id/captain/assistant_responses' do
|
||||
let(:valid_params) do
|
||||
{
|
||||
assistant_response: {
|
||||
question: 'Test question?',
|
||||
answer: 'Test answer',
|
||||
assistant_id: assistant.id
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates a new response if the user is an admin' do
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: valid_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(Captain::AssistantResponse, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
|
||||
expect(json_response[:question]).to eq('Test question?')
|
||||
expect(json_response[:answer]).to eq('Test answer')
|
||||
end
|
||||
|
||||
context 'with invalid params' do
|
||||
let(:invalid_params) do
|
||||
{
|
||||
assistant_response: {
|
||||
question: 'Test',
|
||||
answer: 'Test'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistant_responses",
|
||||
params: invalid_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH /api/v1/accounts/:account_id/captain/assistant_responses/:id' do
|
||||
let!(:response_record) { create(:captain_assistant_response, assistant: assistant) }
|
||||
let(:update_params) do
|
||||
{
|
||||
assistant_response: {
|
||||
question: 'Updated question?',
|
||||
answer: 'Updated answer'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'updates the response if the user is an admin' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistant_responses/#{response_record.id}",
|
||||
params: update_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
|
||||
expect(json_response[:question]).to eq('Updated question?')
|
||||
expect(json_response[:answer]).to eq('Updated answer')
|
||||
end
|
||||
|
||||
context 'with invalid params' do
|
||||
let(:invalid_params) do
|
||||
{
|
||||
assistant_response: {
|
||||
question: '',
|
||||
answer: ''
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistant_responses/#{response_record.id}",
|
||||
params: invalid_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/:account_id/captain/assistant_responses/:id' do
|
||||
let!(:response_record) { create(:captain_assistant_response, assistant: assistant) }
|
||||
|
||||
it 'deletes the response' do
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistant_responses/#{response_record.id}",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(Captain::AssistantResponse, :count).by(-1)
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
end
|
||||
|
||||
context 'with invalid id' do
|
||||
it 'returns not found' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistant_responses/0",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,317 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/assistants' do
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'does not fetch assistants' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants",
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'fetches assistants for the account' do
|
||||
create_list(:captain_assistant, 3, account: account)
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
expect(json_response[:meta]).to eq(
|
||||
{ total_count: 3, page: 1 }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/assistants/{id}' do
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'does not fetch the assistant' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'fetches the assistant' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:id]).to eq(assistant.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/{account.id}/captain/assistants' do
|
||||
let(:valid_attributes) do
|
||||
{
|
||||
assistant: {
|
||||
name: 'New Assistant',
|
||||
description: 'Assistant Description',
|
||||
response_guidelines: ['Be helpful', 'Be concise'],
|
||||
guardrails: ['No harmful content', 'Stay on topic'],
|
||||
config: {
|
||||
product_name: 'Chatwoot',
|
||||
feature_faq: true,
|
||||
feature_memory: false,
|
||||
feature_citation: true
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'does not create an assistant' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants",
|
||||
params: valid_attributes,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'does not create an assistant' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants",
|
||||
params: valid_attributes,
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'creates a new assistant' do
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants",
|
||||
params: valid_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(Captain::Assistant, :count).by(1)
|
||||
|
||||
expect(json_response[:name]).to eq('New Assistant')
|
||||
expect(json_response[:response_guidelines]).to eq(['Be helpful', 'Be concise'])
|
||||
expect(json_response[:guardrails]).to eq(['No harmful content', 'Stay on topic'])
|
||||
expect(json_response[:config][:product_name]).to eq('Chatwoot')
|
||||
expect(json_response[:config][:feature_citation]).to be(true)
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'creates an assistant with feature_citation disabled' do
|
||||
attributes_with_disabled_citation = valid_attributes.deep_dup
|
||||
attributes_with_disabled_citation[:assistant][:config][:feature_citation] = false
|
||||
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants",
|
||||
params: attributes_with_disabled_citation,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(Captain::Assistant, :count).by(1)
|
||||
|
||||
expect(json_response[:config][:feature_citation]).to be(false)
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH /api/v1/accounts/{account.id}/captain/assistants/{id}' do
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
let(:update_attributes) do
|
||||
{
|
||||
assistant: {
|
||||
name: 'Updated Assistant',
|
||||
response_guidelines: ['Updated guideline'],
|
||||
guardrails: ['Updated guardrail'],
|
||||
config: {
|
||||
feature_citation: false
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'does not update the assistant' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
params: update_attributes,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'does not update the assistant' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
params: update_attributes,
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'updates the assistant' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
params: update_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:name]).to eq('Updated Assistant')
|
||||
expect(json_response[:response_guidelines]).to eq(['Updated guideline'])
|
||||
expect(json_response[:guardrails]).to eq(['Updated guardrail'])
|
||||
end
|
||||
|
||||
it 'updates only response_guidelines when only that is provided' do
|
||||
assistant.update!(response_guidelines: ['Original guideline'], guardrails: ['Original guardrail'])
|
||||
original_name = assistant.name
|
||||
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
params: { assistant: { response_guidelines: ['New guideline only'] } },
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:name]).to eq(original_name)
|
||||
expect(json_response[:response_guidelines]).to eq(['New guideline only'])
|
||||
expect(json_response[:guardrails]).to eq(['Original guardrail'])
|
||||
end
|
||||
|
||||
it 'updates only guardrails when only that is provided' do
|
||||
assistant.update!(response_guidelines: ['Original guideline'], guardrails: ['Original guardrail'])
|
||||
original_name = assistant.name
|
||||
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
params: { assistant: { guardrails: ['New guardrail only'] } },
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:name]).to eq(original_name)
|
||||
expect(json_response[:response_guidelines]).to eq(['Original guideline'])
|
||||
expect(json_response[:guardrails]).to eq(['New guardrail only'])
|
||||
end
|
||||
|
||||
it 'updates feature_citation config' do
|
||||
assistant.update!(config: { 'feature_citation' => true })
|
||||
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
params: { assistant: { config: { feature_citation: false } } },
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:config][:feature_citation]).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/{account.id}/captain/assistants/{id}' do
|
||||
let!(:assistant) { create(:captain_assistant, account: account) }
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'does not delete the assistant' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'delete the assistant' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'deletes the assistant' do
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(Captain::Assistant, :count).by(-1)
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/{account.id}/captain/assistants/{id}/playground' do
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
let(:valid_params) do
|
||||
{
|
||||
message_content: 'Hello assistant',
|
||||
message_history: [
|
||||
{ role: 'user', content: 'Previous message' },
|
||||
{ role: 'assistant', content: 'Previous response' }
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/playground",
|
||||
params: valid_params,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'generates a response' do
|
||||
chat_service = instance_double(Captain::Llm::AssistantChatService)
|
||||
allow(Captain::Llm::AssistantChatService).to receive(:new).with(assistant: assistant).and_return(chat_service)
|
||||
allow(chat_service).to receive(:generate_response).and_return({ content: 'Assistant response' })
|
||||
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/playground",
|
||||
params: valid_params,
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(chat_service).to have_received(:generate_response).with(
|
||||
additional_message: valid_params[:message_content],
|
||||
message_history: valid_params[:message_history]
|
||||
)
|
||||
expect(json_response[:content]).to eq('Assistant response')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message_history is not provided' do
|
||||
it 'uses empty array as default' do
|
||||
params_without_history = { message_content: 'Hello assistant' }
|
||||
chat_service = instance_double(Captain::Llm::AssistantChatService)
|
||||
allow(Captain::Llm::AssistantChatService).to receive(:new).with(assistant: assistant).and_return(chat_service)
|
||||
allow(chat_service).to receive(:generate_response).and_return({ content: 'Assistant response' })
|
||||
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/playground",
|
||||
params: params_without_history,
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(chat_service).to have_received(:generate_response).with(
|
||||
additional_message: params_without_history[:message_content],
|
||||
message_history: []
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,143 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::BulkActions', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let!(:pending_responses) do
|
||||
create_list(
|
||||
:captain_assistant_response,
|
||||
2,
|
||||
assistant: assistant,
|
||||
account: account,
|
||||
status: 'pending'
|
||||
)
|
||||
end
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/:account_id/captain/bulk_actions' do
|
||||
context 'when approving responses' do
|
||||
let(:valid_params) do
|
||||
{
|
||||
type: 'AssistantResponse',
|
||||
ids: pending_responses.map(&:id),
|
||||
fields: { status: 'approve' }
|
||||
}
|
||||
end
|
||||
|
||||
it 'approves the responses and returns the updated records' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||
params: valid_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response).to be_an(Array)
|
||||
expect(json_response.length).to eq(2)
|
||||
|
||||
# Verify responses were approved
|
||||
pending_responses.each do |response|
|
||||
expect(response.reload.status).to eq('approved')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when deleting responses' do
|
||||
let(:delete_params) do
|
||||
{
|
||||
type: 'AssistantResponse',
|
||||
ids: pending_responses.map(&:id),
|
||||
fields: { status: 'delete' }
|
||||
}
|
||||
end
|
||||
|
||||
it 'deletes the responses and returns an empty array' do
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||
params: delete_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(Captain::AssistantResponse, :count).by(-2)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response).to eq([])
|
||||
|
||||
# Verify responses were deleted
|
||||
pending_responses.each do |response|
|
||||
expect { response.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid type' do
|
||||
let(:invalid_params) do
|
||||
{
|
||||
type: 'InvalidType',
|
||||
ids: pending_responses.map(&:id),
|
||||
fields: { status: 'approve' }
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||
params: invalid_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(json_response[:success]).to be(false)
|
||||
|
||||
# Verify no changes were made
|
||||
pending_responses.each do |response|
|
||||
expect(response.reload.status).to eq('pending')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with missing parameters' do
|
||||
let(:missing_params) do
|
||||
{
|
||||
type: 'AssistantResponse',
|
||||
fields: { status: 'approve' }
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||
params: missing_params,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(json_response[:success]).to be(false)
|
||||
|
||||
# Verify no changes were made
|
||||
pending_responses.each do |response|
|
||||
expect(response.reload.status).to eq('pending')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with unauthorized user' do
|
||||
let(:unauthorized_user) { create(:user, account: create(:account)) }
|
||||
|
||||
it 'returns unauthorized status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/bulk_actions",
|
||||
params: { type: 'AssistantResponse', ids: [1], fields: { status: 'approve' } },
|
||||
headers: unauthorized_user.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
|
||||
# Verify no changes were made
|
||||
pending_responses.each do |response|
|
||||
expect(response.reload.status).to eq('pending')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,78 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::CopilotMessagesController', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:user) { create(:user, account: account, role: :administrator) }
|
||||
let(:copilot_thread) { create(:captain_copilot_thread, account: account, user: user) }
|
||||
let!(:copilot_message) { create(:captain_copilot_message, copilot_thread: copilot_thread, account: account) }
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/copilot_threads/{thread.id}/copilot_messages' do
|
||||
context 'when it is an authenticated user' do
|
||||
it 'returns all messages' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/copilot_threads/#{copilot_thread.id}/copilot_messages",
|
||||
headers: user.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
json_response = response.parsed_body
|
||||
expect(json_response['payload'].length).to eq(1)
|
||||
expect(json_response['payload'][0]['id']).to eq(copilot_message.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when thread id is invalid' do
|
||||
it 'returns not found error' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/copilot_threads/999999999/copilot_messages",
|
||||
headers: user.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/{account.id}/captain/copilot_threads/{thread.id}/copilot_messages' do
|
||||
context 'when it is an authenticated user' do
|
||||
it 'creates a new message' do
|
||||
message_content = { 'content' => 'This is a test message' }
|
||||
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads/#{copilot_thread.id}/copilot_messages",
|
||||
params: { message: message_content },
|
||||
headers: user.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(CopilotMessage, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(CopilotMessage.last.message).to eq({ 'content' => message_content })
|
||||
expect(CopilotMessage.last.message_type).to eq('user')
|
||||
expect(CopilotMessage.last.copilot_thread_id).to eq(copilot_thread.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when thread does not exist' do
|
||||
it 'returns not found error' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads/999999999/copilot_messages",
|
||||
params: { message: { text: 'Test message' } },
|
||||
headers: user.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when thread belongs to another user' do
|
||||
let(:another_user) { create(:user, account: account) }
|
||||
let(:another_thread) { create(:captain_copilot_thread, account: account, user: another_user) }
|
||||
|
||||
it 'returns not found error' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads/#{another_thread.id}/copilot_messages",
|
||||
params: { message: { text: 'Test message' } },
|
||||
headers: user.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,140 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::CopilotThreads', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:conversation) { create(:conversation, account: account) }
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/copilot_threads' do
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'does not fetch copilot threads' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
it 'fetches copilot threads for the current user' do
|
||||
# Create threads for the current agent
|
||||
create_list(:captain_copilot_thread, 3, account: account, user: agent)
|
||||
# Create threads for another user (should not be included)
|
||||
create_list(:captain_copilot_thread, 2, account: account, user: admin)
|
||||
|
||||
get "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
|
||||
expect(json_response[:payload].map { |thread| thread[:user][:id] }.uniq).to eq([agent.id])
|
||||
end
|
||||
|
||||
it 'returns threads in descending order of creation' do
|
||||
threads = create_list(:captain_copilot_thread, 3, account: account, user: agent)
|
||||
|
||||
get "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].pluck(:id)).to eq(threads.reverse.pluck(:id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/{account.id}/captain/copilot_threads' do
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
let(:valid_params) { { message: 'Hello, how can you help me?', assistant_id: assistant.id, conversation_id: conversation.display_id } }
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
params: valid_params,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
context 'with invalid params' do
|
||||
it 'returns error when message is blank' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
params: { message: '', assistant_id: assistant.id },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(json_response[:error]).to eq('Message is required')
|
||||
end
|
||||
|
||||
it 'returns error when assistant_id is invalid' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
params: { message: 'Hello', assistant_id: 0 },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with valid params' do
|
||||
it 'returns error when usage limit is exceeded' do
|
||||
account.limits = { captain_responses: 2 }
|
||||
account.custom_attributes = { captain_responses_usage: 2 }
|
||||
account.save!
|
||||
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
params: valid_params,
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
|
||||
expect(CopilotMessage.last.message['content']).to eq(
|
||||
'You are out of Copilot credits. You can buy more credits from the billing section.'
|
||||
)
|
||||
end
|
||||
|
||||
it 'creates a new copilot thread with initial message' do
|
||||
account.limits = { captain_responses: 2 }
|
||||
account.custom_attributes = { captain_responses_usage: 0 }
|
||||
account.save!
|
||||
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/copilot_threads",
|
||||
params: valid_params,
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(CopilotThread, :count).by(1)
|
||||
.and change(CopilotMessage, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
|
||||
thread = CopilotThread.last
|
||||
expect(thread.title).to eq(valid_params[:message])
|
||||
expect(thread.user_id).to eq(agent.id)
|
||||
expect(thread.assistant_id).to eq(assistant.id)
|
||||
|
||||
message = thread.copilot_messages.last
|
||||
expect(message.message).to eq({ 'content' => valid_params[:message] })
|
||||
|
||||
expect(Captain::Copilot::ResponseJob).to have_been_enqueued.with(
|
||||
assistant: assistant,
|
||||
conversation_id: valid_params[:conversation_id],
|
||||
user_id: agent.id,
|
||||
copilot_thread_id: thread.id,
|
||||
message: valid_params[:message]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,281 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::CustomTools', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/custom_tools' do
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/custom_tools"
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns success status' do
|
||||
create_list(:captain_custom_tool, 3, account: account)
|
||||
get "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'returns success status and custom tools' do
|
||||
create_list(:captain_custom_tool, 5, account: account)
|
||||
get "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(5)
|
||||
end
|
||||
|
||||
it 'returns only enabled custom tools' do
|
||||
create(:captain_custom_tool, account: account, enabled: true)
|
||||
create(:captain_custom_tool, account: account, enabled: false)
|
||||
get "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(1)
|
||||
expect(json_response[:payload].first[:enabled]).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/custom_tools/{id}' do
|
||||
let(:custom_tool) { create(:captain_custom_tool, account: account) }
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}"
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns success status and custom tool' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:id]).to eq(custom_tool.id)
|
||||
expect(json_response[:title]).to eq(custom_tool.title)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when custom tool does not exist' do
|
||||
it 'returns not found status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/custom_tools/999999",
|
||||
headers: agent.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/{account.id}/captain/custom_tools' do
|
||||
let(:valid_attributes) do
|
||||
{
|
||||
custom_tool: {
|
||||
title: 'Fetch Order Status',
|
||||
description: 'Fetches order status from external API',
|
||||
endpoint_url: 'https://api.example.com/orders/{{ order_id }}',
|
||||
http_method: 'GET',
|
||||
enabled: true,
|
||||
param_schema: [
|
||||
{ name: 'order_id', type: 'string', description: 'The order ID', required: true }
|
||||
]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
params: valid_attributes
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns unauthorized status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
params: valid_attributes,
|
||||
headers: agent.create_new_auth_token
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'creates a new custom tool and returns success status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
params: valid_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:title]).to eq('Fetch Order Status')
|
||||
expect(json_response[:description]).to eq('Fetches order status from external API')
|
||||
expect(json_response[:enabled]).to be(true)
|
||||
expect(json_response[:slug]).to eq('custom_fetch_order_status')
|
||||
expect(json_response[:param_schema]).to eq([
|
||||
{ name: 'order_id', type: 'string', description: 'The order ID', required: true }
|
||||
])
|
||||
end
|
||||
|
||||
context 'with invalid parameters' do
|
||||
let(:invalid_attributes) do
|
||||
{
|
||||
custom_tool: {
|
||||
title: '',
|
||||
endpoint_url: ''
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
params: invalid_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid endpoint URL' do
|
||||
let(:invalid_url_attributes) do
|
||||
{
|
||||
custom_tool: {
|
||||
title: 'Test Tool',
|
||||
endpoint_url: 'http://localhost/api',
|
||||
http_method: 'GET'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/custom_tools",
|
||||
params: invalid_url_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH /api/v1/accounts/{account.id}/captain/custom_tools/{id}' do
|
||||
let(:custom_tool) { create(:captain_custom_tool, account: account) }
|
||||
let(:update_attributes) do
|
||||
{
|
||||
custom_tool: {
|
||||
title: 'Updated Tool Title',
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}",
|
||||
params: update_attributes
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns unauthorized status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}",
|
||||
params: update_attributes,
|
||||
headers: agent.create_new_auth_token
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'updates the custom tool and returns success status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}",
|
||||
params: update_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:title]).to eq('Updated Tool Title')
|
||||
expect(json_response[:enabled]).to be(false)
|
||||
end
|
||||
|
||||
context 'with invalid parameters' do
|
||||
let(:invalid_attributes) do
|
||||
{
|
||||
custom_tool: {
|
||||
title: ''
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}",
|
||||
params: invalid_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/{account.id}/captain/custom_tools/{id}' do
|
||||
let!(:custom_tool) { create(:captain_custom_tool, account: account) }
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}"
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns unauthorized status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}",
|
||||
headers: agent.create_new_auth_token
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'deletes the custom tool and returns no content status' do
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/custom_tools/#{custom_tool.id}",
|
||||
headers: admin.create_new_auth_token
|
||||
end.to change(Captain::CustomTool, :count).by(-1)
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
end
|
||||
|
||||
context 'when custom tool does not exist' do
|
||||
it 'returns not found status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/custom_tools/999999",
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,291 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::Documents', type: :request do
|
||||
let(:account) { create(:account, custom_attributes: { plan_name: 'startups' }) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
let(:assistant2) { create(:captain_assistant, account: account) }
|
||||
let(:document) { create(:captain_document, assistant: assistant, account: account) }
|
||||
let(:captain_limits) do
|
||||
{
|
||||
:startups => { :documents => 1, :responses => 100 }
|
||||
}.with_indifferent_access
|
||||
end
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/:account_id/captain/documents' do
|
||||
context 'when it is an un-authenticated user' do
|
||||
before do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents"
|
||||
end
|
||||
|
||||
it 'returns unauthorized status' do
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
context 'when no filters are applied' do
|
||||
before do
|
||||
create_list(:captain_document, 30, assistant: assistant, account: account)
|
||||
end
|
||||
|
||||
it 'returns the first page of documents' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents", headers: agent.create_new_auth_token, as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(25)
|
||||
expect(json_response[:meta]).to eq({ page: 1, total_count: 30 })
|
||||
end
|
||||
|
||||
it 'returns the second page of documents' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: { page: 2 },
|
||||
headers: agent.create_new_auth_token, as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(5)
|
||||
expect(json_response[:meta]).to eq({ page: 2, total_count: 30 })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when filtering by assistant_id' do
|
||||
before do
|
||||
create_list(:captain_document, 3, assistant: assistant, account: account)
|
||||
create_list(:captain_document, 2, assistant: assistant2, account: account)
|
||||
end
|
||||
|
||||
it 'returns only documents for the specified assistant' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: { assistant_id: assistant.id },
|
||||
headers: agent.create_new_auth_token, as: :json
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
expect(json_response[:payload][0][:assistant][:id]).to eq(assistant.id)
|
||||
end
|
||||
|
||||
it 'returns empty array when assistant has no documents' do
|
||||
new_assistant = create(:captain_assistant, account: account)
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: { assistant_id: new_assistant.id },
|
||||
headers: agent.create_new_auth_token, as: :json
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload]).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when documents belong to different accounts' do
|
||||
let(:other_account) { create(:account) }
|
||||
|
||||
before do
|
||||
create_list(:captain_document, 3, assistant: assistant, account: account)
|
||||
create_list(:captain_document, 2, account: other_account)
|
||||
end
|
||||
|
||||
it 'only returns documents for the current account' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
headers: agent.create_new_auth_token, as: :json
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
document_account_ids = json_response[:payload].pluck(:account_id).uniq
|
||||
expect(document_account_ids).to eq([account.id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with pagination and assistant filter combined' do
|
||||
before do
|
||||
create_list(:captain_document, 30, assistant: assistant, account: account)
|
||||
create_list(:captain_document, 10, assistant: assistant2, account: account)
|
||||
end
|
||||
|
||||
it 'returns paginated results for specific assistant' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: { assistant_id: assistant.id, page: 2 },
|
||||
headers: agent.create_new_auth_token, as: :json
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].length).to eq(5)
|
||||
expect(json_response[:payload][0][:assistant][:id]).to eq(assistant.id)
|
||||
expect(json_response[:meta]).to eq({ page: 2, total_count: 30 })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/:account_id/captain/documents/:id' do
|
||||
context 'when it is an un-authenticated user' do
|
||||
before do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents/#{document.id}"
|
||||
end
|
||||
|
||||
it 'returns unauthorized status' do
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
before do
|
||||
get "/api/v1/accounts/#{account.id}/captain/documents/#{document.id}",
|
||||
headers: agent.create_new_auth_token, as: :json
|
||||
end
|
||||
|
||||
it 'returns success status' do
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
|
||||
it 'returns the requested document' do
|
||||
expect(json_response[:id]).to eq(document.id)
|
||||
expect(json_response[:name]).to eq(document.name)
|
||||
expect(json_response[:external_link]).to eq(document.external_link)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/:account_id/captain/documents' do
|
||||
let(:valid_attributes) do
|
||||
{
|
||||
document: {
|
||||
name: 'Test Document',
|
||||
external_link: 'https://example.com/doc',
|
||||
assistant_id: assistant.id
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
let(:invalid_attributes) do
|
||||
{
|
||||
document: {
|
||||
name: 'Test Document',
|
||||
external_link: 'https://example.com/doc'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
before do
|
||||
post "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: valid_attributes, as: :json
|
||||
end
|
||||
|
||||
it 'returns unauthorized status' do
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns unauthorized' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: valid_attributes,
|
||||
headers: agent.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
context 'with valid parameters' do
|
||||
it 'creates a new document' do
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: valid_attributes,
|
||||
headers: admin.create_new_auth_token
|
||||
end.to change(Captain::Document, :count).by(1)
|
||||
end
|
||||
|
||||
it 'returns success status and the created document' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: valid_attributes,
|
||||
headers: admin.create_new_auth_token, as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:name]).to eq('Test Document')
|
||||
expect(json_response[:external_link]).to eq('https://example.com/doc')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid parameters' do
|
||||
before do
|
||||
post "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: invalid_attributes,
|
||||
headers: admin.create_new_auth_token
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with limits exceeded' do
|
||||
before do
|
||||
create_list(:captain_document, 5, assistant: assistant, account: account)
|
||||
|
||||
create(:installation_config, name: 'CAPTAIN_CLOUD_PLAN_LIMITS', value: captain_limits.to_json)
|
||||
post "/api/v1/accounts/#{account.id}/captain/documents",
|
||||
params: valid_attributes,
|
||||
headers: admin.create_new_auth_token
|
||||
end
|
||||
|
||||
it 'returns an error' do
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/:account_id/captain/documents/:id' do
|
||||
context 'when it is an un-authenticated user' do
|
||||
before do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/documents/#{document.id}"
|
||||
end
|
||||
|
||||
it 'returns unauthorized status' do
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
let!(:document_to_delete) { create(:captain_document, assistant: assistant) }
|
||||
|
||||
it 'deletes the document' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/documents/#{document_to_delete.id}",
|
||||
headers: agent.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
context 'when document exists' do
|
||||
let!(:document_to_delete) { create(:captain_document, assistant: assistant) }
|
||||
|
||||
it 'deletes the document' do
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/documents/#{document_to_delete.id}",
|
||||
headers: admin.create_new_auth_token
|
||||
end.to change(Captain::Document, :count).by(-1)
|
||||
end
|
||||
|
||||
it 'returns no content status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/documents/#{document_to_delete.id}",
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when document does not exist' do
|
||||
before do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/documents/invalid_id",
|
||||
headers: admin.create_new_auth_token
|
||||
end
|
||||
|
||||
it 'returns not found status' do
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,119 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::Inboxes', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
let(:inbox) { create(:inbox, account: account) }
|
||||
let(:inbox2) { create(:inbox, account: account) }
|
||||
let!(:captain_inbox) { create(:captain_inbox, captain_assistant: assistant, inbox: inbox) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/:account_id/captain/assistants/:assistant_id/inboxes' do
|
||||
context 'when user is authorized' do
|
||||
it 'returns a list of inboxes for the assistant' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes",
|
||||
headers: agent.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(json_response[:payload].first[:id]).to eq(captain_inbox.inbox.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is unauthorized' do
|
||||
it 'returns unauthorized status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when assistant does not exist' do
|
||||
it 'returns not found status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/999999/inboxes",
|
||||
headers: agent.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/:account/captain/assistants/:assistant_id/inboxes' do
|
||||
let(:valid_params) do
|
||||
{
|
||||
inbox: {
|
||||
inbox_id: inbox2.id
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when user is authorized' do
|
||||
it 'creates a new captain inbox' do
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes",
|
||||
params: valid_params,
|
||||
headers: admin.create_new_auth_token
|
||||
end.to change(CaptainInbox, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:id]).to eq(inbox2.id)
|
||||
end
|
||||
|
||||
context 'when inbox does not exist' do
|
||||
it 'returns not found status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes",
|
||||
params: { inbox: { inbox_id: 999_999 } },
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when params are invalid' do
|
||||
it 'returns unprocessable entity status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes",
|
||||
params: {},
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is agent' do
|
||||
it 'returns unauthorized status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes",
|
||||
params: valid_params,
|
||||
headers: agent.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/captain/assistants/:assistant_id/inboxes/:inbox_id' do
|
||||
context 'when user is authorized' do
|
||||
it 'deletes the captain inbox' do
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes/#{inbox.id}",
|
||||
headers: admin.create_new_auth_token
|
||||
end.to change(CaptainInbox, :count).by(-1)
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
end
|
||||
|
||||
context 'when captain inbox does not exist' do
|
||||
it 'returns not found status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/inboxes/999999",
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,258 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Api::V1::Accounts::Captain::Scenarios', type: :request do
|
||||
let(:account) { create(:account) }
|
||||
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||
let(:agent) { create(:user, account: account, role: :agent) }
|
||||
let(:assistant) { create(:captain_assistant, account: account) }
|
||||
|
||||
def json_response
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/assistants/{assistant.id}/scenarios' do
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios"
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns success status' do
|
||||
create_list(:captain_scenario, 3, assistant: assistant, account: account)
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(3)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'returns success status and scenarios' do
|
||||
create_list(:captain_scenario, 5, assistant: assistant, account: account)
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(5)
|
||||
end
|
||||
|
||||
it 'returns only enabled scenarios' do
|
||||
create(:captain_scenario, assistant: assistant, account: account, enabled: true)
|
||||
create(:captain_scenario, assistant: assistant, account: account, enabled: false)
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios",
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:payload].length).to eq(1)
|
||||
expect(json_response[:payload].first[:enabled]).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/captain/assistants/{assistant.id}/scenarios/{id}' do
|
||||
let(:scenario) { create(:captain_scenario, assistant: assistant, account: account) }
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}"
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns success status and scenario' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}",
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:id]).to eq(scenario.id)
|
||||
expect(json_response[:title]).to eq(scenario.title)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when scenario does not exist' do
|
||||
it 'returns not found status' do
|
||||
get "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/999999",
|
||||
headers: agent.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/{account.id}/captain/assistants/{assistant.id}/scenarios' do
|
||||
let(:valid_attributes) do
|
||||
{
|
||||
scenario: {
|
||||
title: 'Test Scenario',
|
||||
description: 'Test description',
|
||||
instruction: 'Test instruction',
|
||||
enabled: true,
|
||||
tools: %w[tool1 tool2]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios",
|
||||
params: valid_attributes
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns unauthorized status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios",
|
||||
params: valid_attributes,
|
||||
headers: agent.create_new_auth_token
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'creates a new scenario and returns success status' do
|
||||
expect do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios",
|
||||
params: valid_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
end.to change(Captain::Scenario, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:title]).to eq('Test Scenario')
|
||||
expect(json_response[:description]).to eq('Test description')
|
||||
expect(json_response[:enabled]).to be(true)
|
||||
expect(json_response[:assistant_id]).to eq(assistant.id)
|
||||
end
|
||||
|
||||
context 'with invalid parameters' do
|
||||
let(:invalid_attributes) do
|
||||
{
|
||||
scenario: {
|
||||
title: '',
|
||||
description: '',
|
||||
instruction: ''
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
post "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios",
|
||||
params: invalid_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH /api/v1/accounts/{account.id}/captain/assistants/{assistant.id}/scenarios/{id}' do
|
||||
let(:scenario) { create(:captain_scenario, assistant: assistant, account: account) }
|
||||
let(:update_attributes) do
|
||||
{
|
||||
scenario: {
|
||||
title: 'Updated Scenario Title',
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}",
|
||||
params: update_attributes
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns unauthorized status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}",
|
||||
params: update_attributes,
|
||||
headers: agent.create_new_auth_token
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'updates the scenario and returns success status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}",
|
||||
params: update_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(json_response[:title]).to eq('Updated Scenario Title')
|
||||
expect(json_response[:enabled]).to be(false)
|
||||
end
|
||||
|
||||
context 'with invalid parameters' do
|
||||
let(:invalid_attributes) do
|
||||
{
|
||||
scenario: {
|
||||
title: ''
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns unprocessable entity status' do
|
||||
patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}",
|
||||
params: invalid_attributes,
|
||||
headers: admin.create_new_auth_token,
|
||||
as: :json
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /api/v1/accounts/{account.id}/captain/assistants/{assistant.id}/scenarios/{id}' do
|
||||
let!(:scenario) { create(:captain_scenario, assistant: assistant, account: account) }
|
||||
|
||||
context 'when it is an un-authenticated user' do
|
||||
it 'returns unauthorized status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}"
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an agent' do
|
||||
it 'returns unauthorized status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}",
|
||||
headers: agent.create_new_auth_token
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an admin' do
|
||||
it 'deletes the scenario and returns no content status' do
|
||||
expect do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/#{scenario.id}",
|
||||
headers: admin.create_new_auth_token
|
||||
end.to change(Captain::Scenario, :count).by(-1)
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
end
|
||||
|
||||
context 'when scenario does not exist' do
|
||||
it 'returns not found status' do
|
||||
delete "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}/scenarios/999999",
|
||||
headers: admin.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user