ticket_article_updates_spec.rb 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Gql::Subscriptions::TicketArticleUpdates, type: :graphql do
  4. let(:user) { create(:agent) }
  5. let(:ticket) { create(:ticket) }
  6. let(:variables) { { ticketId: gql.id(ticket) } }
  7. let(:mock_channel) { build_mock_channel }
  8. let(:subscription) do
  9. <<~QUERY
  10. subscription ticketArticleUpdates($ticketId: ID!) {
  11. ticketArticleUpdates(ticketId: $ticketId) {
  12. addArticle {
  13. subject
  14. }
  15. updateArticle {
  16. subject
  17. }
  18. removeArticleId
  19. }
  20. }
  21. QUERY
  22. end
  23. before do
  24. gql.execute(subscription, variables: variables, context: { channel: mock_channel })
  25. end
  26. shared_examples 'check subscription handling with permission' do |is_customer:|
  27. it 'subscribes' do
  28. expect(gql.result.data).to eq({ 'addArticle' => nil, 'updateArticle' => nil, 'removeArticleId' => nil })
  29. end
  30. context 'when a new article is created', :aggregate_failures do
  31. before do
  32. create(:ticket_article, ticket: ticket, subject: 'subscription test', from: 'no-reply@zammad.com')
  33. create(:ticket_article, ticket: ticket, subject: 'subscription test internal', from: 'no-reply@zammad.com', internal: true)
  34. end
  35. let(:public_add_message) do
  36. {
  37. 'addArticle' => { 'subject' => 'subscription test' },
  38. 'updateArticle' => nil,
  39. 'removeArticleId' => nil,
  40. }
  41. end
  42. let(:internal_add_message) do
  43. {
  44. 'addArticle' => { 'subject' => 'subscription test internal' },
  45. 'updateArticle' => nil,
  46. 'removeArticleId' => nil,
  47. }
  48. end
  49. it 'receives article create push message' do
  50. if is_customer
  51. expect(mock_channel.mock_broadcasted_messages).to eq(
  52. [ { result: { 'data' => { 'ticketArticleUpdates' => public_add_message } }, more: true } ]
  53. )
  54. else
  55. expect(mock_channel.mock_broadcasted_messages).to eq(
  56. [
  57. { result: { 'data' => { 'ticketArticleUpdates' => public_add_message } }, more: true },
  58. { result: { 'data' => { 'ticketArticleUpdates' => internal_add_message } }, more: true },
  59. ]
  60. )
  61. end
  62. end
  63. end
  64. context 'when an article is updated', :aggregate_failures do
  65. before do
  66. create(:ticket_article, ticket: ticket, subject: 'subcription test', from: 'no-reply@zammad.com').tap do |article|
  67. mock_channel.mock_broadcasted_messages.clear
  68. article.subject = 'subscription test internal'
  69. article.internal = true
  70. article.save!
  71. article.subject = 'subscription test public'
  72. article.internal = false
  73. article.save!
  74. end
  75. end
  76. let(:internal_update_message) do
  77. {
  78. 'addArticle' => nil,
  79. 'updateArticle' => { 'subject' => 'subscription test internal' },
  80. 'removeArticleId' => nil,
  81. }
  82. end
  83. let(:internal_remove_message) do
  84. {
  85. 'addArticle' => nil,
  86. 'updateArticle' => nil,
  87. 'removeArticleId' => gql.id(Ticket::Article.last),
  88. }
  89. end
  90. let(:public_add_message) do
  91. {
  92. 'addArticle' => { 'subject' => 'subscription test public' },
  93. 'updateArticle' => nil,
  94. 'removeArticleId' => nil,
  95. }
  96. end
  97. let(:public_update_message) do
  98. {
  99. 'addArticle' => nil,
  100. 'updateArticle' => { 'subject' => 'subscription test public' },
  101. 'removeArticleId' => nil,
  102. }
  103. end
  104. it 'receives article update push message' do
  105. if is_customer
  106. expect(mock_channel.mock_broadcasted_messages).to eq(
  107. [
  108. { result: { 'data' => { 'ticketArticleUpdates' => internal_remove_message } }, more: true },
  109. { result: { 'data' => { 'ticketArticleUpdates' => public_add_message } }, more: true },
  110. ]
  111. )
  112. else
  113. expect(mock_channel.mock_broadcasted_messages).to eq(
  114. [
  115. { result: { 'data' => { 'ticketArticleUpdates' => internal_update_message } }, more: true },
  116. { result: { 'data' => { 'ticketArticleUpdates' => public_update_message } }, more: true },
  117. ]
  118. )
  119. end
  120. end
  121. end
  122. context 'when an article is removed', :aggregate_failures do
  123. let!(:article) do
  124. create(:ticket_article, ticket: ticket, subject: 'subcription test', from: 'no-reply@zammad.com').tap do |article|
  125. mock_channel.mock_broadcasted_messages.clear
  126. article.destroy!
  127. end
  128. end
  129. let(:remove_message) do
  130. {
  131. 'addArticle' => nil,
  132. 'updateArticle' => nil,
  133. 'removeArticleId' => gql.id(article),
  134. }
  135. end
  136. it 'receives article remove push message' do
  137. expect(mock_channel.mock_broadcasted_messages).to eq(
  138. [ { result: { 'data' => { 'ticketArticleUpdates' => remove_message } }, more: true } ]
  139. )
  140. end
  141. end
  142. context 'when permission for the ticket is lost' do
  143. before do
  144. ticket.update!(group: create(:group), customer: create(:customer))
  145. create(:ticket_article, ticket: ticket, subject: 'subcription test', from: 'no-reply@zammad.com')
  146. end
  147. it 'does stop receiving ticket updates' do
  148. expect(mock_channel.mock_broadcasted_messages.first[:result]['errors'].first['message']).to eq('not allowed to TicketPolicy#show? this Ticket')
  149. end
  150. end
  151. context 'without ticket' do
  152. let(:ticket) { create(:ticket).tap(&:destroy) }
  153. it 'fetches no ticket' do
  154. expect(gql.result.error_type).to eq(ActiveRecord::RecordNotFound)
  155. end
  156. end
  157. end
  158. shared_examples 'check subscription handling without permission' do
  159. it 'raises authorization error' do
  160. expect(gql.result.error_type).to eq(Exceptions::Forbidden)
  161. end
  162. end
  163. context 'with an agent', authenticated_as: :agent do
  164. let(:user) { agent }
  165. context 'with permission' do
  166. let(:agent) { create(:agent, groups: [ticket.group]) }
  167. include_examples 'check subscription handling with permission', is_customer: false
  168. end
  169. context 'without permission' do
  170. let(:agent) { create(:agent) }
  171. include_examples 'check subscription handling without permission'
  172. end
  173. end
  174. context 'with a customer', authenticated_as: :customer do
  175. let(:user) { customer }
  176. context 'with permission' do
  177. let(:customer) { ticket.customer }
  178. include_examples 'check subscription handling with permission', is_customer: true
  179. end
  180. context 'without permission' do
  181. let(:customer) { create(:customer) }
  182. include_examples 'check subscription handling without permission'
  183. end
  184. end
  185. it_behaves_like 'graphql responds with error if unauthenticated'
  186. end