update_spec.rb 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Gql::Mutations::Ticket::Update, :aggregate_failures, type: :graphql do
  4. let(:query) do
  5. <<~QUERY
  6. mutation ticketUpdate($ticketId: ID!, $input: TicketUpdateInput!) {
  7. ticketUpdate(ticketId: $ticketId, input: $input) {
  8. ticket {
  9. id
  10. title
  11. group {
  12. name
  13. }
  14. priority {
  15. name
  16. }
  17. customer {
  18. fullname
  19. }
  20. owner {
  21. fullname
  22. }
  23. objectAttributeValues {
  24. attribute {
  25. name
  26. }
  27. value
  28. }
  29. }
  30. errors {
  31. message
  32. field
  33. }
  34. }
  35. }
  36. QUERY
  37. end
  38. let(:agent) { create(:agent, groups: [ Group.find_by(name: 'Users')]) }
  39. let(:customer) { create(:customer) }
  40. let(:user) { agent }
  41. let(:group) { agent.groups.first }
  42. let(:priority) { Ticket::Priority.last }
  43. let(:ticket) { create(:ticket, group: agent.groups.first, customer: customer) }
  44. let(:article_payload) { nil }
  45. let(:input_base_payload) do
  46. {
  47. title: 'Ticket Create Mutation Test',
  48. groupId: gql.id(group),
  49. priorityId: gql.id(priority),
  50. customer: { id: gql.id(customer) },
  51. ownerId: gql.id(agent),
  52. article: article_payload
  53. # pending_time: 10.minutes.from_now,
  54. # type: ...
  55. }
  56. end
  57. let(:input_payload) { input_base_payload }
  58. let(:variables) { { ticketId: gql.id(ticket), input: input_payload } }
  59. let(:expected_base_response) do
  60. {
  61. 'id' => gql.id(Ticket.last),
  62. 'title' => 'Ticket Create Mutation Test',
  63. 'owner' => { 'fullname' => agent.fullname },
  64. 'group' => { 'name' => agent.groups.first.name },
  65. 'customer' => { 'fullname' => customer.fullname },
  66. 'priority' => { 'name' => Ticket::Priority.last.name },
  67. 'objectAttributeValues' => [],
  68. }
  69. end
  70. let(:expected_response) do
  71. expected_base_response
  72. end
  73. context 'when updating a ticket' do
  74. context 'with an agent', authenticated_as: :agent do
  75. it 'updates the attributes' do
  76. gql.execute(query, variables: variables)
  77. expect(gql.result.data['ticket']).to eq(expected_response)
  78. end
  79. context 'without title' do
  80. let(:input_payload) { input_base_payload.tap { |h| h[:title] = ' ' } }
  81. it 'fails validation' do
  82. gql.execute(query, variables: variables)
  83. expect(gql.result.error_message).to include('Variable $input of type TicketUpdateInput! was provided invalid value for title')
  84. end
  85. end
  86. context 'with an article payload' do
  87. let(:article_payload) do
  88. {
  89. body: 'dummy',
  90. type: 'note',
  91. }
  92. end
  93. it 'adds a new article with a specific type' do
  94. expect { gql.execute(query, variables: variables) }
  95. .to change(Ticket::Article, :count).by(1)
  96. expect(Ticket.last.articles.last.type.name).to eq('note')
  97. end
  98. it 'adds a new article with a specific sender' do
  99. expect { gql.execute(query, variables: variables) }
  100. .to change(Ticket::Article, :count).by(1)
  101. expect(Ticket.last.articles.last.sender.name).to eq('Agent')
  102. end
  103. context 'with time unit' do
  104. let(:time_accounting_enabled) { true }
  105. let(:article_payload) do
  106. {
  107. body: 'dummy',
  108. type: 'web',
  109. timeUnit: 123,
  110. }
  111. end
  112. before do
  113. Setting.set('time_accounting', time_accounting_enabled)
  114. end
  115. it 'adds a new article with time unit' do
  116. expect { gql.execute(query, variables: variables) }
  117. .to change(Ticket::Article, :count).by(1)
  118. expect(Ticket.last.articles.last.ticket_time_accounting.time_unit).to eq(123)
  119. end
  120. context 'when time accounting disabled' do
  121. let(:time_accounting_enabled) { false }
  122. it 'does not create ticket article' do
  123. expect { gql.execute(query, variables: variables) }
  124. .not_to change(Ticket::Article, :count)
  125. expect(gql.result.error_message)
  126. .to match('Time Accounting is not enabled')
  127. end
  128. end
  129. end
  130. context 'with active secure mailing (S/MIME)' do
  131. before do
  132. Setting.set('smime_integration', true)
  133. end
  134. it 'adds a new article' do
  135. expect { gql.execute(query, variables: variables) }
  136. .to change(Ticket::Article, :count).by(1)
  137. expect(Ticket.last.articles.last.type.name).to eq('note')
  138. end
  139. end
  140. end
  141. context 'with custom object_attribute', db_strategy: :reset do
  142. let(:object_attribute) do
  143. screens = { create: { 'admin.organization': { shown: true, required: false } } }
  144. create(:object_manager_attribute_text, object_name: 'Ticket', screens: screens).tap do |_oa|
  145. ObjectManager::Attribute.migration_execute
  146. end
  147. end
  148. let(:input_payload) do
  149. input_base_payload.merge(
  150. {
  151. objectAttributeValues: [ { name: object_attribute.name, value: 'object_attribute_value' } ]
  152. }
  153. )
  154. end
  155. let(:expected_response) do
  156. expected_base_response.merge(
  157. {
  158. 'objectAttributeValues' => [{ 'attribute' => { 'name'=>object_attribute.name }, 'value' => 'object_attribute_value' }]
  159. }
  160. )
  161. end
  162. it 'updates the attributes' do
  163. gql.execute(query, variables: variables)
  164. expect(gql.result.data['ticket']).to eq(expected_response)
  165. end
  166. end
  167. context 'when moving the ticket into a group with only :change permission' do
  168. let(:group) { create(:group) }
  169. before do
  170. user.groups << group
  171. user.group_names_access_map = { user.groups.first.name => %w[read change], group.name => ['change'] }
  172. end
  173. it 'updates the ticket, but returns an error trying to access the new ticket' do
  174. gql.execute(query, variables: variables)
  175. expect(ticket.reload.group_id).to eq(group.id)
  176. expect(gql.result.payload['data']['ticketUpdate']).to eq({ 'ticket' => nil, 'errors' => nil }) # Mutation did run, but data retrieval was not authorized.
  177. expect(gql.result.payload['errors'].first['message']).to eq('Access forbidden by Gql::Types::TicketType')
  178. expect(gql.result.payload['errors'].first['extensions']['type']).to eq('Exceptions::Forbidden')
  179. end
  180. end
  181. context 'with no permission to the group' do
  182. let(:group) { create(:group) }
  183. it 'raises an error', :aggregate_failures do
  184. gql.execute(query, variables: variables)
  185. expect(gql.result.error_type).to eq(Exceptions::Forbidden)
  186. expect(gql.result.error_message).to eq('Access forbidden by Gql::Types::GroupType')
  187. end
  188. end
  189. end
  190. context 'with a customer', authenticated_as: :customer do
  191. let(:input_payload) { input_base_payload.tap { |h| h.delete(:customer) } }
  192. let(:expected_response) do
  193. expected_base_response.merge(
  194. {
  195. 'owner' => { 'fullname' => nil },
  196. 'priority' => { 'name' => Ticket::Priority.where(default_create: true).first.name },
  197. }
  198. )
  199. end
  200. it 'updates the ticket with filtered values' do
  201. gql.execute(query, variables: variables)
  202. expect(gql.result.data['ticket']).to eq(expected_response)
  203. end
  204. context 'when sending a different customerId' do
  205. let(:input_payload) { input_base_payload.tap { |h| h[:customer][:id] = gql.id(create(:customer)) } }
  206. it 'fails creating a ticket with permission exception' do
  207. gql.execute(query, variables: variables)
  208. expect(gql.result.error_type).to eq(Exceptions::Forbidden)
  209. expect(gql.result.error_message).to eq('Access forbidden by Gql::Types::UserType')
  210. end
  211. end
  212. context 'with an article payload' do
  213. let(:article_payload) do
  214. {
  215. body: 'dummy',
  216. type: 'web',
  217. }
  218. end
  219. it 'adds a new article with a specific type' do
  220. expect { gql.execute(query, variables: variables) }
  221. .to change(Ticket::Article, :count).by(1)
  222. expect(Ticket.last.articles.last.type.name).to eq('web')
  223. end
  224. it 'adds a new article with a specific sender' do
  225. expect { gql.execute(query, variables: variables) }
  226. .to change(Ticket::Article, :count).by(1)
  227. expect(Ticket.last.articles.last.sender.name).to eq('Customer')
  228. end
  229. end
  230. end
  231. end
  232. end