123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- RSpec.describe Gql::Subscriptions::TicketArticleUpdates, type: :graphql do
- let(:user) { create(:agent) }
- let(:ticket) { create(:ticket) }
- let(:variables) { { ticketId: gql.id(ticket) } }
- let(:mock_channel) { build_mock_channel }
- let(:subscription) do
- <<~QUERY
- subscription ticketArticleUpdates($ticketId: ID!) {
- ticketArticleUpdates(ticketId: $ticketId) {
- addArticle {
- subject
- }
- updateArticle {
- subject
- }
- removeArticleId
- }
- }
- QUERY
- end
- before do
- gql.execute(subscription, variables: variables, context: { channel: mock_channel })
- end
- shared_examples 'check subscription handling with permission' do |is_customer:|
- it 'subscribes' do
- expect(gql.result.data).to eq({ 'addArticle' => nil, 'updateArticle' => nil, 'removeArticleId' => nil })
- end
- context 'when a new article is created', :aggregate_failures do
- before do
- create(:ticket_article, ticket: ticket, subject: 'subscription test', from: 'no-reply@zammad.com')
- create(:ticket_article, ticket: ticket, subject: 'subscription test internal', from: 'no-reply@zammad.com', internal: true)
- end
- let(:public_add_message) do
- {
- 'addArticle' => { 'subject' => 'subscription test' },
- 'updateArticle' => nil,
- 'removeArticleId' => nil,
- }
- end
- let(:internal_add_message) do
- {
- 'addArticle' => { 'subject' => 'subscription test internal' },
- 'updateArticle' => nil,
- 'removeArticleId' => nil,
- }
- end
- it 'receives article create push message' do
- if is_customer
- expect(mock_channel.mock_broadcasted_messages).to eq(
- [ { result: { 'data' => { 'ticketArticleUpdates' => public_add_message } }, more: true } ]
- )
- else
- expect(mock_channel.mock_broadcasted_messages).to eq(
- [
- { result: { 'data' => { 'ticketArticleUpdates' => public_add_message } }, more: true },
- { result: { 'data' => { 'ticketArticleUpdates' => internal_add_message } }, more: true },
- ]
- )
- end
- end
- end
- context 'when an article is updated', :aggregate_failures do
- before do
- create(:ticket_article, ticket: ticket, subject: 'subcription test', from: 'no-reply@zammad.com').tap do |article|
- mock_channel.mock_broadcasted_messages.clear
- article.subject = 'subscription test internal'
- article.internal = true
- article.save!
- article.subject = 'subscription test public'
- article.internal = false
- article.save!
- end
- end
- let(:internal_update_message) do
- {
- 'addArticle' => nil,
- 'updateArticle' => { 'subject' => 'subscription test internal' },
- 'removeArticleId' => nil,
- }
- end
- let(:internal_remove_message) do
- {
- 'addArticle' => nil,
- 'updateArticle' => nil,
- 'removeArticleId' => gql.id(Ticket::Article.last),
- }
- end
- let(:public_add_message) do
- {
- 'addArticle' => { 'subject' => 'subscription test public' },
- 'updateArticle' => nil,
- 'removeArticleId' => nil,
- }
- end
- let(:public_update_message) do
- {
- 'addArticle' => nil,
- 'updateArticle' => { 'subject' => 'subscription test public' },
- 'removeArticleId' => nil,
- }
- end
- it 'receives article update push message' do
- if is_customer
- expect(mock_channel.mock_broadcasted_messages).to eq(
- [
- { result: { 'data' => { 'ticketArticleUpdates' => internal_remove_message } }, more: true },
- { result: { 'data' => { 'ticketArticleUpdates' => public_add_message } }, more: true },
- ]
- )
- else
- expect(mock_channel.mock_broadcasted_messages).to eq(
- [
- { result: { 'data' => { 'ticketArticleUpdates' => internal_update_message } }, more: true },
- { result: { 'data' => { 'ticketArticleUpdates' => public_update_message } }, more: true },
- ]
- )
- end
- end
- end
- context 'when an article is removed', :aggregate_failures do
- let!(:article) do
- create(:ticket_article, ticket: ticket, subject: 'subcription test', from: 'no-reply@zammad.com').tap do |article|
- mock_channel.mock_broadcasted_messages.clear
- article.destroy!
- end
- end
- let(:remove_message) do
- {
- 'addArticle' => nil,
- 'updateArticle' => nil,
- 'removeArticleId' => gql.id(article),
- }
- end
- it 'receives article remove push message' do
- expect(mock_channel.mock_broadcasted_messages).to eq(
- [ { result: { 'data' => { 'ticketArticleUpdates' => remove_message } }, more: true } ]
- )
- end
- end
- context 'when permission for the ticket is lost' do
- before do
- ticket.update!(group: create(:group), customer: create(:customer))
- create(:ticket_article, ticket: ticket, subject: 'subcription test', from: 'no-reply@zammad.com')
- end
- it 'does stop receiving ticket updates' do
- expect(mock_channel.mock_broadcasted_messages.first[:result]['errors'].first['message']).to eq('not allowed to TicketPolicy#show? this Ticket')
- end
- end
- context 'without ticket' do
- let(:ticket) { create(:ticket).tap(&:destroy) }
- it 'fetches no ticket' do
- expect(gql.result.error_type).to eq(ActiveRecord::RecordNotFound)
- end
- end
- end
- shared_examples 'check subscription handling without permission' do
- it 'raises authorization error' do
- expect(gql.result.error_type).to eq(Exceptions::Forbidden)
- end
- end
- context 'with an agent', authenticated_as: :agent do
- let(:user) { agent }
- context 'with permission' do
- let(:agent) { create(:agent, groups: [ticket.group]) }
- include_examples 'check subscription handling with permission', is_customer: false
- end
- context 'without permission' do
- let(:agent) { create(:agent) }
- include_examples 'check subscription handling without permission'
- end
- end
- context 'with a customer', authenticated_as: :customer do
- let(:user) { customer }
- context 'with permission' do
- let(:customer) { ticket.customer }
- include_examples 'check subscription handling with permission', is_customer: true
- end
- context 'without permission' do
- let(:customer) { create(:customer) }
- include_examples 'check subscription handling without permission'
- end
- end
- it_behaves_like 'graphql responds with error if unauthenticated'
- end
|