zammad/spec/requests/ticket/shared_draft/starts_controller_spec.rb

336 lines
10 KiB
Ruby

# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
require 'rails_helper'
RSpec.describe 'Ticket Shared Drafts Start API endpoints', authenticated_as: :agent, type: :request do
let(:group_a) { create(:group, shared_drafts: true) }
let(:group_b) { create(:group, shared_drafts: true) }
let(:group_c) { create(:group, shared_drafts: false) }
let(:group_d) { create(:group, shared_drafts: true) }
let(:role_group_d) { create(:role, :agent, groups: [group_d]) }
let(:draft_a) { create(:ticket_shared_draft_start, group: group_a) }
let(:draft_b) { create(:ticket_shared_draft_start, group: group_b) }
let(:draft_c) { create(:ticket_shared_draft_start, group: group_c) }
let(:draft_d) { create(:ticket_shared_draft_start, group: group_d) }
let(:agent) do
user = create(:agent, roles: [Role.find_by(name: 'Agent'), role_group_d])
user.user_groups.create! group: group_a, access: :full
user.user_groups.create! group: group_c, access: :full
user
end
let(:other_agent) { create(:agent) }
let(:customer) { create(:customer) }
let(:form_id) { SecureRandom.uuid }
let(:base_params) do
{
name: 'draft name',
group_id: group_a.id,
form_id: form_id,
content: { attrs: true }
}
end
let(:path) { '/api/v1/tickets/shared_drafts' }
let(:path_draft_a) { "#{path}/#{draft_a.id}" }
let(:path_draft_b) { "#{path}/#{draft_b.id}" }
let(:path_draft_d) { "#{path}/#{draft_d.id}" }
let(:path_draft_nonexistant) { "#{path}/asd" }
describe 'request handling' do
describe '#index' do
it 'returns drafts that user has access to' do
draft_a && draft_b && draft_d
get path, as: :json
expect(json_response).to include('shared_draft_ids' => [draft_a.id, draft_d.id])
end
it 'returns empty array when no drafts available' do
get path, as: :json
expect(json_response).to include('shared_draft_ids' => [])
end
it 'raises error when user has no permissions', authenticated_as: :customer do
get path, as: :json
expect(response).to have_http_status(:forbidden)
end
end
describe '#show' do
it 'returns draft' do
get path_draft_a, as: :json
expect(json_response).to include('shared_draft_id' => draft_a.id)
end
it 'returns 404 when draft does not exist' do
get path_draft_nonexistant, as: :json
expect(response).to have_http_status(:not_found)
end
it 'returns 404 when user has no permissions to drafts', authenticated_as: :other_agent do
get path_draft_b, as: :json
expect(response).to have_http_status(:forbidden)
end
it 'returns 404 when user has no permissions to this draft' do
get path_draft_b, as: :json
expect(response).to have_http_status(:not_found)
end
it 'returns error when user has no permissions', authenticated_as: :customer do
get path_draft_b, as: :json
expect(response).to have_http_status(:forbidden)
end
it 'grants access via role groups' do
get path_draft_d, as: :json
expect(json_response).to include('shared_draft_id' => draft_d.id)
end
end
describe '#create' do
it 'creates draft' do
post path, params: base_params, as: :json
expect(Ticket::SharedDraftStart).to exist json_response['shared_draft_id']
end
it 'creates draft with attachment' do
create(:store, :image, o_id: form_id)
post path, params: base_params, as: :json
new_draft = Ticket::SharedDraftStart.find json_response['shared_draft_id']
expect(new_draft.attachments).to be_one
end
it 'verifies user has access to given group' do
post path, params: base_params.merge(group_id: group_b.id), as: :json
expect(json_response).to include 'error_human' => %r{does not have access}
end
it 'grants access via role groups' do
post path, params: base_params.merge(group_id: group_d.id), as: :json
expect(Ticket::SharedDraftStart).to exist json_response['shared_draft_id']
end
it 'raises error when user has no create permission on any group', authenticated_as: :other_agent do
post path, params: base_params, as: :json
expect(response).to have_http_status(:forbidden)
end
it 'raises error when user has no permissions', authenticated_as: :customer do
post path, params: base_params, as: :json
expect(response).to have_http_status(:forbidden)
end
end
describe '#update' do
it 'updates draft' do
patch path_draft_a, params: base_params, as: :json
expect(draft_a.reload).to have_attributes(content: { attrs: true })
end
it 'updates draft with attachment' do
create(:store, :image, o_id: form_id)
expect { patch path_draft_a, params: base_params, as: :json }
.to change { draft_a.attachments.count }
.by(1)
end
it 'updates draft to have no attachments' do
create(:store, :image, o_id: draft_a.id, object: draft_a.class.name)
expect { patch path_draft_a, params: base_params, as: :json }
.to change { draft_a.attachments.count }
.by(-1)
end
it 'returns 404 when draft does not exist' do
patch path_draft_nonexistant, params: base_params, as: :json
expect(response).to have_http_status(:not_found)
end
it 'changes draft group' do
agent.user_groups.create! group: group_b, access: :full
patch path_draft_b, params: base_params.merge(group_id: group_b.id), as: :json
expect(draft_b.reload.group).to eq group_b
end
it 'returns updated draft ID' do
patch path_draft_a, params: base_params, as: :json
expect(json_response).to include 'shared_draft_id' => draft_a.id
end
it 'verifies user has access to given groups' do
patch path_draft_a, params: base_params.merge(group_id: group_b.id), as: :json
expect(response).to have_http_status(:unprocessable_content)
end
it 'grants access via role groups' do
patch path_draft_d, params: base_params.merge(group_id: group_d.id), as: :json
expect(json_response).to include 'shared_draft_id' => draft_d.id
end
it 'returns error when user has no permissions', authenticated_as: :customer do
patch path_draft_a, params: base_params, as: :json
expect(response).to have_http_status(:forbidden)
end
end
describe '#destroy' do
it 'destroys draft' do
delete path_draft_a, as: :json
expect(Ticket::SharedDraftStart).not_to exist draft_a.id
end
it 'grants access via role groups' do
delete path_draft_d, as: :json
expect(Ticket::SharedDraftStart).not_to exist draft_d.id
end
it 'returns 404 when draft does not exist' do
delete path_draft_nonexistant, as: :json
expect(response).to have_http_status(:not_found)
end
it 'returns 404 when user has no permissions to this draft' do
delete path_draft_b, as: :json
expect(response).to have_http_status(:not_found)
end
it 'returns error when user has no permissions', authenticated_as: :customer do
delete path_draft_b, as: :json
expect(response).to have_http_status(:forbidden)
end
end
describe '#import_attachments' do
let(:import_path_a) { "#{path_draft_a}/import_attachments" }
let(:import_path_d) { "#{path_draft_d}/import_attachments" }
let(:import_params) do
{
form_id: form_id
}
end
it 'imports attachments from draft to given form ID' do
create(:store, :image, o_id: draft_a.id, object: draft_a.class.name)
expect { post import_path_a, params: import_params, as: :json }
.to change { Store.list(object: 'UploadCache', o_id: form_id).count }
.by(1)
end
it 'grants access via role groups' do
create(:store, :image, o_id: draft_d.id, object: draft_d.class.name)
expect { post import_path_d, params: import_params, as: :json }
.to change { Store.list(object: 'UploadCache', o_id: form_id).count }
.by(1)
end
it 'returns success if draft has no attachments' do
post import_path_a, params: import_params, as: :json
expect(response).to have_http_status(:ok)
end
end
end
describe 'clean up' do
it 'removes draft when creating a ticket' do
post_new_ticket group_a.id, draft_a.id
expect(Ticket::SharedDraftStart).not_to exist(draft_a.id)
end
it 'grants access via role groups' do
post_new_ticket group_d.id, draft_d.id
expect(Ticket::SharedDraftStart).not_to exist(draft_d.id)
end
it 'not removes draft when fails creating a ticket' do
post_new_ticket group_a.id, draft_a.id, valid: false
expect(Ticket::SharedDraftStart).to exist(draft_a.id)
end
it 'raises error if draft is not applicable in this context' do
post_new_ticket group_b.id, draft_a.id
expect(response).to have_http_status(:unprocessable_content)
end
it 'keeps draft if not applicable in this context' do
post_new_ticket group_b.id, draft_a.id
expect(Ticket::SharedDraftStart).to exist(draft_a.id)
end
it 'raises error if group does not support drafts' do
post_new_ticket group_c.id, draft_c.id
expect(response).to have_http_status(:unprocessable_content)
end
it 'succeeds when draft does not exist' do
post_new_ticket group_a.id, 1_234
expect(response).to have_http_status(:created)
end
def post_new_ticket(group_id, shared_draft_id, valid: true)
params = {
title: 'a new ticket #1',
group_id: group_id,
customer_id: create(:customer).id,
shared_draft_id: shared_draft_id,
article: {
content_type: 'text/plain',
body: valid ? 'some body' : nil,
sender: 'Customer',
type: 'note',
},
}
post '/api/v1/tickets', params: params, as: :json
end
end
end