From 22911f8616130034cb98f3e87da89979a6d6cbca Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 20 Feb 2020 14:34:03 +0100 Subject: [PATCH] Refactoring: Improve performance by pushing Ticket create screen information on demand to the client instead of checking every X seconds via the Scheduler. --- app/controllers/sessions/collection_ticket.rb | 15 +- app/jobs/collection_update_job.rb | 50 ++++ app/jobs/ticket_create_screen_job.rb | 29 +++ app/models/concerns/has_collection_update.rb | 34 +++ app/models/concerns/has_groups.rb | 1 + app/models/concerns/has_roles.rb | 17 ++ .../has_ticket_create_screen_impact.rb | 27 +++ app/models/email_address.rb | 3 + app/models/group.rb | 2 + app/models/macro.rb | 3 + app/models/permission.rb | 1 + app/models/role.rb | 2 + app/models/signature.rb | 2 + app/models/ticket/article/sender.rb | 2 + app/models/ticket/article/type.rb | 2 + app/models/ticket/priority.rb | 2 + app/models/ticket/state.rb | 1 + app/models/user.rb | 4 +- .../user/has_ticket_create_screen_impact.rb | 15 ++ lib/sessions/backend/collections.rb | 60 ----- lib/sessions/backend/collections/base.rb | 98 -------- .../backend/collections/email_address.rb | 4 - lib/sessions/backend/collections/group.rb | 3 - lib/sessions/backend/collections/macro.rb | 4 - .../backend/collections/permission.rb | 3 - lib/sessions/backend/collections/role.rb | 3 - lib/sessions/backend/collections/signature.rb | 4 - .../collections/ticket_article_sender.rb | 3 - .../collections/ticket_article_type.rb | 3 - .../backend/collections/ticket_priority.rb | 3 - .../backend/collections/ticket_state.rb | 3 - lib/sessions/backend/ticket_create.rb | 44 ---- lib/sessions/client.rb | 2 - spec/factories/ticket/article/sender.rb | 7 + spec/factories/ticket/article/type.rb | 8 + .../concerns/has_collection_update_spec.rb | 40 ++++ .../has_ticket_create_screen_impact_spec.rb | 174 ++++++++++++++ .../has_collection_update_examples.rb | 52 +++++ ...as_ticket_create_screen_impact_examples.rb | 44 ++++ spec/models/email_address_spec.rb | 3 + spec/models/group_spec.rb | 4 + spec/models/macro_spec.rb | 6 + spec/models/permission_spec.rb | 3 + spec/models/role_spec.rb | 4 + spec/models/signature_spec.rb | 6 + spec/models/ticket/article/sender_spec.rb | 6 + spec/models/ticket/article/type_spec.rb | 6 + spec/models/ticket/priority_spec.rb | 2 + spec/models/ticket/state_spec.rb | 2 + ...as_ticket_create_screen_impact_examples.rb | 161 +++++++++++++ spec/models/user_spec.rb | 24 +- spec/system/examples/text_modules_examples.rb | 3 +- test/unit/session_basic_test.rb | 154 ------------ test/unit/session_collections_test.rb | 221 ------------------ test/unit/session_enhanced_test.rb | 78 ------- 55 files changed, 752 insertions(+), 705 deletions(-) create mode 100644 app/jobs/collection_update_job.rb create mode 100644 app/jobs/ticket_create_screen_job.rb create mode 100644 app/models/concerns/has_collection_update.rb create mode 100644 app/models/concerns/has_ticket_create_screen_impact.rb create mode 100644 app/models/user/has_ticket_create_screen_impact.rb delete mode 100644 lib/sessions/backend/collections.rb delete mode 100644 lib/sessions/backend/collections/base.rb delete mode 100644 lib/sessions/backend/collections/email_address.rb delete mode 100644 lib/sessions/backend/collections/group.rb delete mode 100644 lib/sessions/backend/collections/macro.rb delete mode 100644 lib/sessions/backend/collections/permission.rb delete mode 100644 lib/sessions/backend/collections/role.rb delete mode 100644 lib/sessions/backend/collections/signature.rb delete mode 100644 lib/sessions/backend/collections/ticket_article_sender.rb delete mode 100644 lib/sessions/backend/collections/ticket_article_type.rb delete mode 100644 lib/sessions/backend/collections/ticket_priority.rb delete mode 100644 lib/sessions/backend/collections/ticket_state.rb delete mode 100644 lib/sessions/backend/ticket_create.rb create mode 100644 spec/factories/ticket/article/sender.rb create mode 100644 spec/factories/ticket/article/type.rb create mode 100644 spec/jobs/concerns/has_collection_update_spec.rb create mode 100644 spec/jobs/concerns/has_ticket_create_screen_impact_spec.rb create mode 100644 spec/models/concerns/has_collection_update_examples.rb create mode 100644 spec/models/concerns/has_ticket_create_screen_impact_examples.rb create mode 100644 spec/models/macro_spec.rb create mode 100644 spec/models/signature_spec.rb create mode 100644 spec/models/ticket/article/sender_spec.rb create mode 100644 spec/models/ticket/article/type_spec.rb create mode 100644 spec/models/user/has_ticket_create_screen_impact_examples.rb delete mode 100644 test/unit/session_collections_test.rb diff --git a/app/controllers/sessions/collection_ticket.rb b/app/controllers/sessions/collection_ticket.rb index 12db49ef1..93ee33c8c 100644 --- a/app/controllers/sessions/collection_ticket.rb +++ b/app/controllers/sessions/collection_ticket.rb @@ -4,10 +4,6 @@ module ExtraCollection def session( collections, assets, user ) # all ticket stuff - collections[ Macro.to_app_model ] = [] - Macro.all.each do |item| - assets = item.assets(assets) - end collections[ Ticket::StateType.to_app_model ] = [] Ticket::StateType.all.each do |item| assets = item.assets(assets) @@ -30,13 +26,20 @@ module ExtraCollection end if user.permissions?(['ticket.agent', 'admin.channel_email']) - # all signatures + collections[ Macro.to_app_model ] = [] + Macro.all.each do |item| + assets = item.assets(assets) + end + collections[ TextModule.to_app_model ] = [] + TextModule.all.each do |item| + assets = item.assets(assets) + end + collections[ Signature.to_app_model ] = [] Signature.all.each do |item| assets = item.assets(assets) end - # all email addresses collections[ EmailAddress.to_app_model ] = [] EmailAddress.all.each do |item| assets = item.assets(assets) diff --git a/app/jobs/collection_update_job.rb b/app/jobs/collection_update_job.rb new file mode 100644 index 000000000..b334ce05c --- /dev/null +++ b/app/jobs/collection_update_job.rb @@ -0,0 +1,50 @@ +class CollectionUpdateJob < ApplicationJob + include HasActiveJobLock + + def lock_key + # "CollectionUpdateJob/:model" + "#{self.class.name}/#{arguments[0]}" + end + + def perform(model) + model = model.safe_constantize + return if model.blank? + + assets = {} + all = [] + model.order(id: :asc).find_each do |record| + assets = record.assets(assets) + all.push record.attributes_with_association_ids + end + + return if all.blank? + + Sessions.list.each do |client_id, data| + next if client_id.blank? + + user_id = data&.dig(:user, 'id') + next if user_id.blank? + + # check permission based access + if model.collection_push_permission_value.present? + user = User.lookup(id: user_id) + next if !user&.permissions?(model.collection_push_permission_value) + end + + Rails.logger.debug { "push assets for push_collection #{model} for user #{user_id}" } + Sessions.send(client_id, { + data: assets, + event: 'loadAssets', + }) + + Rails.logger.debug { "push push_collection #{model} for user #{user_id}" } + Sessions.send(client_id, { + event: 'resetCollection', + data: { + model.to_app_model => all, + }, + }) + end + + end +end diff --git a/app/jobs/ticket_create_screen_job.rb b/app/jobs/ticket_create_screen_job.rb new file mode 100644 index 000000000..be6a6ce71 --- /dev/null +++ b/app/jobs/ticket_create_screen_job.rb @@ -0,0 +1,29 @@ +class TicketCreateScreenJob < ApplicationJob + include HasActiveJobLock + + def perform + Sessions.list.each do |client_id, data| + next if client_id.blank? + + user_id = data&.dig(:user, 'id') + next if user_id.blank? + + user = User.lookup(id: user_id) + next if !user&.permissions?('ticket.agent') + + # get attributes to update + ticket_create_attributes = Ticket::ScreenOptions.attributes_to_change( + current_user: user, + ) + + # no data exists + next if ticket_create_attributes.blank? + + Rails.logger.error "push ticket_create for user #{user.id}" + Sessions.send(client_id, { + event: 'ticket_create_attributes', + data: ticket_create_attributes, + }) + end + end +end diff --git a/app/models/concerns/has_collection_update.rb b/app/models/concerns/has_collection_update.rb new file mode 100644 index 000000000..4cb60720b --- /dev/null +++ b/app/models/concerns/has_collection_update.rb @@ -0,0 +1,34 @@ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ +module HasCollectionUpdate + extend ActiveSupport::Concern + + included do + after_commit :push_collection_to_clients + end + + # methods defined here are going to extend the class, not the instance of it + class_methods do + +=begin + +define required permissions to push collection to web app + +class Model < ApplicationModel + include HasCollectionUpdate + collection_push_permission('some_permission') +end + +=end + attr_accessor :collection_push_permission_value + + def collection_push_permission(*permission) + @collection_push_permission_value = permission + end + end + + def push_collection_to_clients + return if Setting.get('import_mode') + + CollectionUpdateJob.set(wait: 10.seconds).perform_later(self.class.name) + end +end diff --git a/app/models/concerns/has_groups.rb b/app/models/concerns/has_groups.rb index 4c78ff07a..08abd846f 100644 --- a/app/models/concerns/has_groups.rb +++ b/app/models/concerns/has_groups.rb @@ -250,6 +250,7 @@ module HasGroups yield self.group_access_buffer = nil cache_delete + push_ticket_create_screen_background_job end def process_group_access_buffer diff --git a/app/models/concerns/has_roles.rb b/app/models/concerns/has_roles.rb index 16952d88a..112748d7b 100644 --- a/app/models/concerns/has_roles.rb +++ b/app/models/concerns/has_roles.rb @@ -2,6 +2,14 @@ module HasRoles extend ActiveSupport::Concern + included do + has_and_belongs_to_many :roles, + before_add: %i[validate_agent_limit_by_role validate_roles], + after_add: %i[cache_update check_notifications push_ticket_create_screen_for_role_change], + before_remove: :last_admin_check_by_role, + after_remove: %i[cache_update push_ticket_create_screen_for_role_change] + end + # Checks a given Group( ID) for given access(es) for the instance associated roles. # # @example Group ID param @@ -36,6 +44,15 @@ module HasRoles ) end + def push_ticket_create_screen_for_role_change(role) + return if Setting.get('import_mode') + + permission = Permission.lookup(name: 'ticket.agent') + return if !role.permissions.exists?(id: permission.id) + + push_ticket_create_screen_background_job + end + # methods defined here are going to extend the class, not the instance of it class_methods do diff --git a/app/models/concerns/has_ticket_create_screen_impact.rb b/app/models/concerns/has_ticket_create_screen_impact.rb new file mode 100644 index 000000000..99a381432 --- /dev/null +++ b/app/models/concerns/has_ticket_create_screen_impact.rb @@ -0,0 +1,27 @@ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ +module HasTicketCreateScreenImpact + extend ActiveSupport::Concern + + included do + after_commit :push_ticket_create_screen + end + + def push_ticket_create_screen? + return true if destroyed? + + %w[id name active].any? do |attribute| + saved_change_to_attribute?(attribute) + end + end + + def push_ticket_create_screen + return if Setting.get('import_mode') + return if !push_ticket_create_screen? + + push_ticket_create_screen_background_job + end + + def push_ticket_create_screen_background_job + TicketCreateScreenJob.set(wait: 10.seconds).perform_later + end +end diff --git a/app/models/email_address.rb b/app/models/email_address.rb index e0e611e83..c3c44cfa1 100644 --- a/app/models/email_address.rb +++ b/app/models/email_address.rb @@ -2,6 +2,7 @@ class EmailAddress < ApplicationModel include ChecksLatestChangeObserved + include HasCollectionUpdate has_many :groups, after_add: :cache_update, after_remove: :cache_update belongs_to :channel, optional: true @@ -15,6 +16,8 @@ class EmailAddress < ApplicationModel after_update :update_email_address_id before_destroy :delete_group_reference + collection_push_permission('ticket.agent') + =begin check and if channel not exists reset configured channels for email addresses diff --git a/app/models/group.rb b/app/models/group.rb index 880a41151..17c3cae05 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -7,6 +7,8 @@ class Group < ApplicationModel include ChecksLatestChangeObserved include HasHistory include HasObjectManagerAttributesValidation + include HasCollectionUpdate + include HasTicketCreateScreenImpact belongs_to :email_address, optional: true belongs_to :signature, optional: true diff --git a/app/models/macro.rb b/app/models/macro.rb index 1004ebe93..3b9655970 100644 --- a/app/models/macro.rb +++ b/app/models/macro.rb @@ -4,10 +4,13 @@ class Macro < ApplicationModel include ChecksClientNotification include ChecksLatestChangeObserved include CanSeed + include HasCollectionUpdate store :perform validates :name, presence: true validates :ux_flow_next_up, inclusion: { in: %w[none next_task next_from_overview] } has_and_belongs_to_many :groups, after_add: :cache_update, after_remove: :cache_update, class_name: 'Group' + + collection_push_permission('ticket.agent') end diff --git a/app/models/permission.rb b/app/models/permission.rb index afe05193f..3ed97586b 100644 --- a/app/models/permission.rb +++ b/app/models/permission.rb @@ -3,6 +3,7 @@ class Permission < ApplicationModel include ChecksClientNotification include ChecksLatestChangeObserved + include HasCollectionUpdate has_and_belongs_to_many :roles validates :name, presence: true diff --git a/app/models/role.rb b/app/models/role.rb index e4ad5f729..240c639ae 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -6,6 +6,8 @@ class Role < ApplicationModel include ChecksClientNotification include ChecksLatestChangeObserved include HasGroups + include HasCollectionUpdate + include HasTicketCreateScreenImpact include Role::Assets diff --git a/app/models/signature.rb b/app/models/signature.rb index 04053bad0..49074fb73 100644 --- a/app/models/signature.rb +++ b/app/models/signature.rb @@ -3,10 +3,12 @@ class Signature < ApplicationModel include ChecksLatestChangeObserved include ChecksHtmlSanitized + include HasCollectionUpdate has_many :groups, after_add: :cache_update, after_remove: :cache_update validates :name, presence: true sanitized_html :body + collection_push_permission('ticket.agent') end diff --git a/app/models/ticket/article/sender.rb b/app/models/ticket/article/sender.rb index 261ab8b82..1d8655182 100644 --- a/app/models/ticket/article/sender.rb +++ b/app/models/ticket/article/sender.rb @@ -2,5 +2,7 @@ class Ticket::Article::Sender < ApplicationModel include ChecksLatestChangeObserved + include HasCollectionUpdate + validates :name, presence: true end diff --git a/app/models/ticket/article/type.rb b/app/models/ticket/article/type.rb index 2c2f26c86..f5f3bd0d3 100644 --- a/app/models/ticket/article/type.rb +++ b/app/models/ticket/article/type.rb @@ -2,5 +2,7 @@ class Ticket::Article::Type < ApplicationModel include ChecksLatestChangeObserved + include HasCollectionUpdate + validates :name, presence: true end diff --git a/app/models/ticket/priority.rb b/app/models/ticket/priority.rb index 38392a7b5..06c85b35e 100644 --- a/app/models/ticket/priority.rb +++ b/app/models/ticket/priority.rb @@ -1,6 +1,8 @@ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ class Ticket::Priority < ApplicationModel include CanBeImported + include HasCollectionUpdate + self.table_name = 'ticket_priorities' validates :name, presence: true diff --git a/app/models/ticket/state.rb b/app/models/ticket/state.rb index 630c5b04e..48740e3b0 100644 --- a/app/models/ticket/state.rb +++ b/app/models/ticket/state.rb @@ -2,6 +2,7 @@ class Ticket::State < ApplicationModel include CanBeImported include ChecksLatestChangeObserved + include HasCollectionUpdate belongs_to :state_type, class_name: 'Ticket::StateType', inverse_of: :states, optional: true belongs_to :next_state, class_name: 'Ticket::State', optional: true diff --git a/app/models/user.rb b/app/models/user.rb index f76a57289..c2cb3f6b8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -12,13 +12,13 @@ class User < ApplicationModel include HasGroups include HasRoles include HasObjectManagerAttributesValidation - + include HasTicketCreateScreenImpact + include User::HasTicketCreateScreenImpact include User::ChecksAccess include User::Assets include User::Search include User::SearchIndex - has_and_belongs_to_many :roles, after_add: %i[cache_update check_notifications], after_remove: :cache_update, before_add: %i[validate_agent_limit_by_role validate_roles], before_remove: :last_admin_check_by_role, class_name: 'Role' has_and_belongs_to_many :organizations, after_add: :cache_update, after_remove: :cache_update, class_name: 'Organization' has_many :tokens, after_add: :cache_update, after_remove: :cache_update has_many :authorizations, after_add: :cache_update, after_remove: :cache_update diff --git a/app/models/user/has_ticket_create_screen_impact.rb b/app/models/user/has_ticket_create_screen_impact.rb new file mode 100644 index 000000000..abed3dae6 --- /dev/null +++ b/app/models/user/has_ticket_create_screen_impact.rb @@ -0,0 +1,15 @@ +# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ +class User + module HasTicketCreateScreenImpact + extend ActiveSupport::Concern + + def push_ticket_create_screen? + return true if destroyed? + return false if %w[id login firstname lastname preferences active].none? do |attribute| + saved_change_to_attribute?(attribute) + end + + permissions?('ticket.agent') + end + end +end diff --git a/lib/sessions/backend/collections.rb b/lib/sessions/backend/collections.rb deleted file mode 100644 index 8f8683d71..000000000 --- a/lib/sessions/backend/collections.rb +++ /dev/null @@ -1,60 +0,0 @@ -class Sessions::Backend::Collections < Sessions::Backend::Base - - def initialize(user, asset_lookup, client, client_id, ttl = 10) - @user = user - @client = client - @client_id = client_id - @ttl = ttl - @asset_lookup = asset_lookup - @backends = backend - end - - def push - return if !to_run? - - @time_now = Time.zone.now.to_i - - results = [] - @backends.each do |backend| - result = backend.push - if result - results.push result - end - end - results - end - - def user=(user) - @user = user - - # update stored user in backends, too - @backends.each do |backend| - backend.user = user - end - end - - def backend - - # auto population collections - backends = [] - - # load collections to deliver from external files - dir = File.expand_path('../../..', __dir__) - files = Dir.glob("#{dir}/lib/sessions/backend/collections/*.rb") - files.each do |file| - file.gsub!("#{dir}/lib/", '') - file.gsub!(/\.rb$/, '') - next if file.classify == 'Sessions::Backend::Collections::Base' - - #puts "LOAD #{file.classify}---" - #next if file == '' - backend = file.classify.constantize.new(@user, @asset_lookup, @client, @client_id, @ttl) - if backend - backends.push backend - end - end - - backends - end - -end diff --git a/lib/sessions/backend/collections/base.rb b/lib/sessions/backend/collections/base.rb deleted file mode 100644 index 3e30da062..000000000 --- a/lib/sessions/backend/collections/base.rb +++ /dev/null @@ -1,98 +0,0 @@ -class Sessions::Backend::Collections::Base < Sessions::Backend::Base - class << self; attr_accessor :model, :permissions end - - attr_writer :user - attr_writer :time_now - - def initialize(user, asset_lookup, client, client_id, ttl) - @user = user - @client = client - @client_id = client_id - @ttl = ttl - @asset_lookup = asset_lookup - @last_change = nil - end - - def to_run? - return true if !@time_now - return true if Time.zone.now.to_i > (@time_now + @ttl) - - false - end - - def load - - # get whole collection - self.class.model.constantize.all.order(id: :asc) - end - - def push - return if !to_run? - - @time_now = Time.zone.now.to_i - - # check permission based access - if self.class.permissions - return if !@user.permissions?(self.class.permissions) - end - - # check if update has been done - last_change = self.class.model.constantize.latest_change - return if last_change.to_s == @last_change - - @last_change = last_change.to_s - - # load current data - items = load - - return if items.blank? - - # get relations of data - all = [] - items.each do |item| - all.push item.attributes_with_association_ids - end - - # collect assets - @time_now = Time.zone.now.to_i - assets = {} - items.each do |item| - next if !asset_needed?(item) - - assets = asset_push(item, assets) - end - if !@client - return { - collection: { - items.first.class.to_app_model => all, - }, - assets: assets, - } - end - @client.log "push assets for push_collection #{items.first.class} for user #{@user.id}" - @client.send( - data: assets, - event: 'loadAssets', - ) - - @client.log "push push_collection #{items.first.class} for user #{@user.id}" - @client.send( - event: 'resetCollection', - data: { - items.first.class.to_app_model => all, - }, - ) - end - - def self.model_set(model) - @model = model - end - - def self.add_if_permission(key) - if !@permissions - @permissions = [] - end - @permissions.push key - end - -end diff --git a/lib/sessions/backend/collections/email_address.rb b/lib/sessions/backend/collections/email_address.rb deleted file mode 100644 index e7aacae66..000000000 --- a/lib/sessions/backend/collections/email_address.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Sessions::Backend::Collections::EmailAddress < Sessions::Backend::Collections::Base - model_set 'EmailAddress' - add_if_permission 'ticket.agent' -end diff --git a/lib/sessions/backend/collections/group.rb b/lib/sessions/backend/collections/group.rb deleted file mode 100644 index 2858fdf5c..000000000 --- a/lib/sessions/backend/collections/group.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Sessions::Backend::Collections::Group < Sessions::Backend::Collections::Base - model_set 'Group' -end diff --git a/lib/sessions/backend/collections/macro.rb b/lib/sessions/backend/collections/macro.rb deleted file mode 100644 index a85f3fa60..000000000 --- a/lib/sessions/backend/collections/macro.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Sessions::Backend::Collections::Macro < Sessions::Backend::Collections::Base - model_set 'Macro' - add_if_permission 'ticket.agent' -end diff --git a/lib/sessions/backend/collections/permission.rb b/lib/sessions/backend/collections/permission.rb deleted file mode 100644 index ec186485d..000000000 --- a/lib/sessions/backend/collections/permission.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Sessions::Backend::Collections::Permission < Sessions::Backend::Collections::Base - model_set 'Permission' -end diff --git a/lib/sessions/backend/collections/role.rb b/lib/sessions/backend/collections/role.rb deleted file mode 100644 index fb3e05df1..000000000 --- a/lib/sessions/backend/collections/role.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Sessions::Backend::Collections::Role < Sessions::Backend::Collections::Base - model_set 'Role' -end diff --git a/lib/sessions/backend/collections/signature.rb b/lib/sessions/backend/collections/signature.rb deleted file mode 100644 index 7645b1de9..000000000 --- a/lib/sessions/backend/collections/signature.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Sessions::Backend::Collections::Signature < Sessions::Backend::Collections::Base - model_set 'Signature' - add_if_permission 'ticket.agent' -end diff --git a/lib/sessions/backend/collections/ticket_article_sender.rb b/lib/sessions/backend/collections/ticket_article_sender.rb deleted file mode 100644 index 9e40da1a6..000000000 --- a/lib/sessions/backend/collections/ticket_article_sender.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Sessions::Backend::Collections::TicketArticleSender < Sessions::Backend::Collections::Base - model_set 'Ticket::Article::Sender' -end diff --git a/lib/sessions/backend/collections/ticket_article_type.rb b/lib/sessions/backend/collections/ticket_article_type.rb deleted file mode 100644 index a110bdcd7..000000000 --- a/lib/sessions/backend/collections/ticket_article_type.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Sessions::Backend::Collections::TicketArticleType < Sessions::Backend::Collections::Base - model_set 'Ticket::Article::Type' -end diff --git a/lib/sessions/backend/collections/ticket_priority.rb b/lib/sessions/backend/collections/ticket_priority.rb deleted file mode 100644 index 6e76ff215..000000000 --- a/lib/sessions/backend/collections/ticket_priority.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Sessions::Backend::Collections::TicketPriority < Sessions::Backend::Collections::Base - model_set 'Ticket::Priority' -end diff --git a/lib/sessions/backend/collections/ticket_state.rb b/lib/sessions/backend/collections/ticket_state.rb deleted file mode 100644 index 9a5592c7c..000000000 --- a/lib/sessions/backend/collections/ticket_state.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Sessions::Backend::Collections::TicketState < Sessions::Backend::Collections::Base - model_set 'Ticket::State' -end diff --git a/lib/sessions/backend/ticket_create.rb b/lib/sessions/backend/ticket_create.rb deleted file mode 100644 index a6b6601ae..000000000 --- a/lib/sessions/backend/ticket_create.rb +++ /dev/null @@ -1,44 +0,0 @@ -class Sessions::Backend::TicketCreate < Sessions::Backend::Base - - def load - # get attributes to update - ticket_create_attributes = Ticket::ScreenOptions.attributes_to_change( - current_user: @user, - ) - - # no data exists - return if !ticket_create_attributes - - # no change exists - return if @last_change == ticket_create_attributes - - # remember last state - @last_change = ticket_create_attributes - - ticket_create_attributes - end - - def push - return if !to_run? - - @time_now = Time.zone.now.to_i - - data = load - - return if !data - - if !@client - return { - event: 'ticket_create_attributes', - data: data, - } - end - - @client.log "push ticket_create for user #{@user.id}" - @client.send( - event: 'ticket_create_attributes', - data: data, - ) - end - -end diff --git a/lib/sessions/client.rb b/lib/sessions/client.rb index efa201384..6209f87b2 100644 --- a/lib/sessions/client.rb +++ b/lib/sessions/client.rb @@ -12,9 +12,7 @@ class Sessions::Client backends = [ 'Sessions::Backend::TicketOverviewList', - 'Sessions::Backend::Collections', 'Sessions::Backend::ActivityStream', - 'Sessions::Backend::TicketCreate', ] asset_lookup = {} diff --git a/spec/factories/ticket/article/sender.rb b/spec/factories/ticket/article/sender.rb new file mode 100644 index 000000000..ca46f937c --- /dev/null +++ b/spec/factories/ticket/article/sender.rb @@ -0,0 +1,7 @@ +FactoryBot.define do + factory :'ticket/article/sender', aliases: %i[ticket_article_sender] do + sequence(:name) { |n| "#{n} sender" } + updated_by_id { 1 } + created_by_id { 1 } + end +end diff --git a/spec/factories/ticket/article/type.rb b/spec/factories/ticket/article/type.rb new file mode 100644 index 000000000..ff07ae6dd --- /dev/null +++ b/spec/factories/ticket/article/type.rb @@ -0,0 +1,8 @@ +FactoryBot.define do + factory :'ticket/article/type', aliases: %i[ticket_article_type] do + sequence(:name) { |n| "#{n} type" } + communication { true } + updated_by_id { 1 } + created_by_id { 1 } + end +end diff --git a/spec/jobs/concerns/has_collection_update_spec.rb b/spec/jobs/concerns/has_collection_update_spec.rb new file mode 100644 index 000000000..85cae901a --- /dev/null +++ b/spec/jobs/concerns/has_collection_update_spec.rb @@ -0,0 +1,40 @@ +require 'rails_helper' + +RSpec.describe HasCollectionUpdate, type: :job do + + context 'with groups' do + + let!(:group) { create(:group) } + + it 'create should enqueue no job' do + collection_jobs = enqueued_jobs.select do |job| + job[:job] == CollectionUpdateJob && job[:args][0] == 'Group' + end + + expect(collection_jobs.count).to be(1) + end + + context 'updating attribute' do + before do + clear_jobs + end + + context 'name' do + it 'enqueues a job' do + expect { group.update!(name: 'new name') }.to have_enqueued_job(CollectionUpdateJob).with('Group') + end + end + + context 'updated_at' do + it 'enqueues a job' do + expect { group.touch }.to have_enqueued_job(CollectionUpdateJob).with('Group') + end + end + end + + it 'delete should enqueue a job' do + clear_jobs + expect { group.destroy! }.to have_enqueued_job(CollectionUpdateJob).with('Group') + end + end +end diff --git a/spec/jobs/concerns/has_ticket_create_screen_impact_spec.rb b/spec/jobs/concerns/has_ticket_create_screen_impact_spec.rb new file mode 100644 index 000000000..27d205806 --- /dev/null +++ b/spec/jobs/concerns/has_ticket_create_screen_impact_spec.rb @@ -0,0 +1,174 @@ +require 'rails_helper' + +RSpec.describe HasTicketCreateScreenImpact, type: :job do + + context 'with groups' do + let!(:group) { create(:group) } + + it 'create should enqueue no job' do + collection_jobs = enqueued_jobs.select do |job| + job[:job] == TicketCreateScreenJob + end + expect(collection_jobs.count).to be(1) + end + + context 'updating attribute' do + before do + clear_jobs + end + + context 'name' do + it 'enqueues a job' do + expect { group.update!(name: 'new name') }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'active' do + it 'enqueues a job' do + expect { group.update!(active: false) }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'updated_at' do + it 'enqueues a job' do + expect { group.touch }.to have_enqueued_job(TicketCreateScreenJob) + end + end + end + + it 'delete should enqueue no job' do + clear_jobs + expect { group.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'with roles' do + let!(:role) { create(:role) } + + it 'create should enqueue no job' do + collection_jobs = enqueued_jobs.select do |job| + job[:job] == TicketCreateScreenJob + end + expect(collection_jobs.count).to be(1) + end + + context 'updating attribute' do + + before do + clear_jobs + end + + context 'name' do + it 'enqueues a job' do + expect { role.update!(name: 'new name') }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'active' do + it 'enqueues a job' do + expect { role.update!(active: false) }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'updated_at' do + it 'enqueues no job' do + expect { role.touch }.to have_enqueued_job(TicketCreateScreenJob) + end + end + end + + it 'delete should enqueue no job' do + clear_jobs + expect { role.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'with users' do + + let!(:customer) { create(:user, roles: Role.where(name: 'Customer')) } + let!(:agent) { create(:user, roles: Role.where(name: 'Agent')) } + let!(:admin) { create(:user, roles: Role.where(name: 'Admin')) } + + let(:customer_new) { create(:user, roles: Role.where(name: 'Customer')) } + let(:agent_new) { create(:user, roles: Role.where(name: 'Agent')) } + let(:admin_new) { create(:user, roles: Role.where(name: 'Admin')) } + + context 'creating' do + before do + clear_jobs + end + + it 'customer should enqueue no job' do + customer_new + collection_jobs = enqueued_jobs.select do |job| + job[:job] == TicketCreateScreenJob + end + expect(collection_jobs.count).to be(0) + end + it 'agent should enqueue a job' do + agent_new + collection_jobs = enqueued_jobs.select do |job| + job[:job] == TicketCreateScreenJob + end + expect(collection_jobs.count).to be(1) + end + it 'admin should enqueue no job' do + admin_new + collection_jobs = enqueued_jobs.select do |job| + job[:job] == TicketCreateScreenJob + end + expect(collection_jobs.count).to be(0) + end + end + + context 'updating attribute' do + before do + clear_jobs + end + + context 'firstname field for' do + it 'customer should enqueue no job' do + expect { customer.update!(firstname: 'new firstname') }.not_to have_enqueued_job(TicketCreateScreenJob) + end + it 'agent should enqueue a job' do + expect { agent.update!(firstname: 'new firstname') }.to have_enqueued_job(TicketCreateScreenJob) + end + it 'admin should enqueue no job' do + expect { admin.update!(firstname: 'new firstname') }.not_to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'active field for' do + it 'customer should enqueue no job' do + expect { customer.update!(active: false) }.not_to have_enqueued_job(TicketCreateScreenJob) + end + it 'agent should enqueue a job' do + expect { agent.update!(active: false) }.to have_enqueued_job(TicketCreateScreenJob) + end + it 'admin should enqueue no job' do + admin_new # Prevend "Minimum one user needs to have admin permissions." + clear_jobs + expect { admin.update!(active: false) }.not_to have_enqueued_job(TicketCreateScreenJob) + end + end + end + + context 'deleting' do + before do + clear_jobs + end + + it 'customer should enqueue a job' do + expect { customer.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + it 'agent should enqueue a job' do + expect { agent.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + it 'admin should enqueue a job' do + expect { admin.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + end + +end diff --git a/spec/models/concerns/has_collection_update_examples.rb b/spec/models/concerns/has_collection_update_examples.rb new file mode 100644 index 000000000..3efb7a6c0 --- /dev/null +++ b/spec/models/concerns/has_collection_update_examples.rb @@ -0,0 +1,52 @@ +RSpec.shared_examples 'HasCollectionUpdate' do |collection_factory:| + + context '#push_collection_to_clients', performs_jobs: true do + subject { create(collection_factory) } + + context 'creating a record' do + + it 'enqueues a CollectionUpdateJob job' do + expect { subject }.to have_enqueued_job(CollectionUpdateJob).with(described_class.name) + end + end + + context 'record exists' do + + before do + subject + clear_jobs + end + + context 'attribute updated' do + + context 'name' do + it 'enqueues a CollectionUpdateJob job' do + expect do + + if subject.respond_to?(:name) + subject.name = 'New name' + else + # EmailAdress has no `name` attribute + subject.realname = 'New name' + end + subject.save! + end.to have_enqueued_job(CollectionUpdateJob).with(described_class.name) + end + end + + context 'updated_at' do + it 'enqueues a CollectionUpdateJob job' do + expect { subject.touch }.to have_enqueued_job(CollectionUpdateJob).with(described_class.name) + end + end + end + + context 'record is deleted' do + + it 'enqueues a CollectionUpdateJob job' do + expect { subject.destroy! }.to have_enqueued_job(CollectionUpdateJob).with(described_class.name) + end + end + end + end +end diff --git a/spec/models/concerns/has_ticket_create_screen_impact_examples.rb b/spec/models/concerns/has_ticket_create_screen_impact_examples.rb new file mode 100644 index 000000000..c9c3c63f8 --- /dev/null +++ b/spec/models/concerns/has_ticket_create_screen_impact_examples.rb @@ -0,0 +1,44 @@ +RSpec.shared_examples 'HasTicketCreateScreenImpact' do |create_screen_factory:| + + context '#push_ticket_create_screen', performs_jobs: true do + subject { create(create_screen_factory) } + + context 'creating a record' do + it 'enqueues a TicketCreateScreenJob job' do + expect { subject }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'record exists' do + + before do + subject + clear_jobs + end + + context 'attribute updated' do + + context 'name' do + it 'enqueues a TicketCreateScreenJob job' do + expect do + subject.name = 'New name' + subject.save! + end.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'updated_at' do + it 'enqueues a TicketCreateScreenJob job' do + expect { subject.touch }.to have_enqueued_job(TicketCreateScreenJob) + end + end + end + + context 'record is deleted' do + it 'enqueues a TicketCreateScreenJob job' do + expect { subject.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + end + end + end +end diff --git a/spec/models/email_address_spec.rb b/spec/models/email_address_spec.rb index ac5fc9e10..2e6d364cb 100644 --- a/spec/models/email_address_spec.rb +++ b/spec/models/email_address_spec.rb @@ -1,6 +1,9 @@ require 'rails_helper' +require 'models/concerns/has_collection_update_examples' RSpec.describe EmailAddress, type: :model do + it_behaves_like 'HasCollectionUpdate', collection_factory: :email_address + subject(:email_address) { create(:email_address) } describe 'Attributes:' do diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index e2230c2b1..8f72010fa 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -2,9 +2,13 @@ require 'rails_helper' require 'models/application_model_examples' require 'models/concerns/can_be_imported_examples' require 'models/concerns/has_object_manager_attributes_validation_examples' +require 'models/concerns/has_collection_update_examples' +require 'models/concerns/has_ticket_create_screen_impact_examples' RSpec.describe Group, type: :model do it_behaves_like 'ApplicationModel' it_behaves_like 'CanBeImported' it_behaves_like 'HasObjectManagerAttributesValidation' + it_behaves_like 'HasCollectionUpdate', collection_factory: :group + it_behaves_like 'HasTicketCreateScreenImpact', create_screen_factory: :group end diff --git a/spec/models/macro_spec.rb b/spec/models/macro_spec.rb new file mode 100644 index 000000000..465c2098e --- /dev/null +++ b/spec/models/macro_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' +require 'models/concerns/has_collection_update_examples' + +RSpec.describe Macro, type: :model do + it_behaves_like 'HasCollectionUpdate', collection_factory: :macro +end diff --git a/spec/models/permission_spec.rb b/spec/models/permission_spec.rb index 68b79c0c3..ba506e637 100644 --- a/spec/models/permission_spec.rb +++ b/spec/models/permission_spec.rb @@ -1,6 +1,9 @@ require 'rails_helper' +require 'models/concerns/has_collection_update_examples' RSpec.describe Permission, type: :model do + it_behaves_like 'HasCollectionUpdate', collection_factory: :permission + describe '.with_parents' do context 'when given a simple string (no dots)' do it 'returns an array containing only that string' do diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 02a4fc0fb..3a5a92dcc 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -2,11 +2,15 @@ require 'rails_helper' require 'models/application_model_examples' require 'models/concerns/can_be_imported_examples' require 'models/concerns/has_groups_examples' +require 'models/concerns/has_collection_update_examples' +require 'models/concerns/has_ticket_create_screen_impact_examples' RSpec.describe Role do it_behaves_like 'ApplicationModel' it_behaves_like 'CanBeImported' it_behaves_like 'HasGroups', group_access_factory: :role + it_behaves_like 'HasCollectionUpdate', collection_factory: :role + it_behaves_like 'HasTicketCreateScreenImpact', create_screen_factory: :role subject(:role) { create(:role) } diff --git a/spec/models/signature_spec.rb b/spec/models/signature_spec.rb new file mode 100644 index 000000000..a441a0da5 --- /dev/null +++ b/spec/models/signature_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' +require 'models/concerns/has_collection_update_examples' + +RSpec.describe Signature, type: :model do + it_behaves_like 'HasCollectionUpdate', collection_factory: :signature +end diff --git a/spec/models/ticket/article/sender_spec.rb b/spec/models/ticket/article/sender_spec.rb new file mode 100644 index 000000000..4579a5aae --- /dev/null +++ b/spec/models/ticket/article/sender_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' +require 'models/concerns/has_collection_update_examples' + +RSpec.describe Ticket::Article::Sender, type: :model do + it_behaves_like 'HasCollectionUpdate', collection_factory: :ticket_article_sender +end diff --git a/spec/models/ticket/article/type_spec.rb b/spec/models/ticket/article/type_spec.rb new file mode 100644 index 000000000..4c72e092f --- /dev/null +++ b/spec/models/ticket/article/type_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' +require 'models/concerns/has_collection_update_examples' + +RSpec.describe Ticket::Article::Type, type: :model do + it_behaves_like 'HasCollectionUpdate', collection_factory: :ticket_article_type +end diff --git a/spec/models/ticket/priority_spec.rb b/spec/models/ticket/priority_spec.rb index a26b89dfb..67860793a 100644 --- a/spec/models/ticket/priority_spec.rb +++ b/spec/models/ticket/priority_spec.rb @@ -1,10 +1,12 @@ require 'rails_helper' require 'models/application_model_examples' require 'models/concerns/can_be_imported_examples' +require 'models/concerns/has_collection_update_examples' RSpec.describe Ticket::Priority, type: :model do it_behaves_like 'ApplicationModel' it_behaves_like 'CanBeImported' + it_behaves_like 'HasCollectionUpdate', collection_factory: :ticket_priority describe 'Default state' do describe 'of whole table:' do diff --git a/spec/models/ticket/state_spec.rb b/spec/models/ticket/state_spec.rb index 48369554b..f502587b2 100644 --- a/spec/models/ticket/state_spec.rb +++ b/spec/models/ticket/state_spec.rb @@ -1,10 +1,12 @@ require 'rails_helper' require 'models/application_model_examples' require 'models/concerns/can_be_imported_examples' +require 'models/concerns/has_collection_update_examples' RSpec.describe Ticket::State, type: :model do it_behaves_like 'ApplicationModel' it_behaves_like 'CanBeImported' + it_behaves_like 'HasCollectionUpdate', collection_factory: :ticket_state describe 'Default state' do describe 'of whole table:' do diff --git a/spec/models/user/has_ticket_create_screen_impact_examples.rb b/spec/models/user/has_ticket_create_screen_impact_examples.rb new file mode 100644 index 000000000..86f3f50b0 --- /dev/null +++ b/spec/models/user/has_ticket_create_screen_impact_examples.rb @@ -0,0 +1,161 @@ +RSpec.shared_examples 'HasTicketCreateScreenImpact' do + + context '#push_ticket_create_screen', performs_jobs: true do + shared_examples 'relevant User Role' do |role| + + context "relevant User Role is '#{role}'" do + + subject { create(:user, roles: Role.where(name: role)) } + + context 'creating a record' do + it 'enqueues TicketCreateScreenJob' do + expect { subject }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'record exists' do + + before do + subject + clear_jobs + end + + context 'attribute updated' do + it 'enqueues TicketCreateScreenJob' do + expect { subject.update!(firstname: 'new firstname') }.to have_enqueued_job(TicketCreateScreenJob) + end + + context 'permission association changes' do + + context 'Group' do + + let!(:group) { create(:group) } + + before { clear_jobs } + + it 'enqueues TicketCreateScreenJob' do + expect do + subject.group_names_access_map = { + group.name => ['full'], + } + end.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'Role' do + context 'to relevant' do + + let!(:roles) { create_list(:agent_role, 1) } + + before { clear_jobs } + + it 'enqueues TicketCreateScreenJob' do + expect { subject.update!(roles: roles) }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'to irrelevant' do + + let!(:roles) { create_list(:role, 3) } + + before { clear_jobs } + + it 'enqueues TicketCreateScreenJob' do + expect { subject.update!(roles: roles) }.to have_enqueued_job(TicketCreateScreenJob) + end + end + end + end + end + + context 'record is deleted' do + it 'enqueues TicketCreateScreenJob' do + expect { subject.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + end + end + end + end + + shared_examples 'irrelevant User Role' do |role| + + context "irrelevant User Role is '#{role}'" do + + subject { create(:user, roles: Role.where(name: role)) } + + context 'creating a record' do + it 'does not enqueue TicketCreateScreenJob job' do + expect { subject }.not_to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'record exists' do + + before do + subject + clear_jobs + end + + context 'attribute updated' do + it 'enqueues no TicketCreateScreenJob job' do + expect { subject.update!(firstname: 'new firstname') }.not_to have_enqueued_job(TicketCreateScreenJob) + end + + context 'permission association changes', last_admin_check: false do + + context 'Group' do + + let!(:group) { create(:group) } + + before { clear_jobs } + + it 'enqueues TicketCreateScreenJob' do + expect do + subject.group_names_access_map = { + group.name => ['full'], + } + end.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'Role' do + + context 'to relevant' do + + let!(:roles) { create_list(:agent_role, 3) } + + before { clear_jobs } + + it 'enqueues TicketCreateScreenJob' do + expect { subject.update!(roles: roles) }.to have_enqueued_job(TicketCreateScreenJob) + end + end + + context 'to irrelevant' do + + let!(:roles) { create_list(:role, 3) } + + before { clear_jobs } + + it 'does not enqueue TicketCreateScreenJob' do + expect { subject.update!(roles: roles) }.not_to have_enqueued_job(TicketCreateScreenJob) + end + end + end + end + end + + context 'record is deleted' do + it 'enqueues TicketCreateScreenJob job' do + expect { subject.destroy! }.to have_enqueued_job(TicketCreateScreenJob) + end + end + end + end + end + + include_examples 'relevant User Role', 'Agent' + include_examples 'irrelevant User Role', 'Customer' + include_examples 'irrelevant User Role', 'Admin' + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 1f9b36bb7..54255c4e3 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -7,7 +7,7 @@ require 'models/concerns/has_groups_permissions_examples' require 'models/concerns/has_xss_sanitized_note_examples' require 'models/concerns/can_be_imported_examples' require 'models/concerns/has_object_manager_attributes_validation_examples' -require 'models/user/can_lookup_search_index_attributes_examples' +require 'models/user/has_ticket_create_screen_impact_examples' RSpec.describe User, type: :model do subject(:user) { create(:user) } @@ -24,7 +24,7 @@ RSpec.describe User, type: :model do it_behaves_like 'HasGroups and Permissions', group_access_no_permission_factory: :user it_behaves_like 'CanBeImported' it_behaves_like 'HasObjectManagerAttributesValidation' - it_behaves_like 'CanLookupSearchIndexAttributes' + it_behaves_like 'HasTicketCreateScreenImpact' describe 'Class methods:' do describe '.authenticate' do @@ -1144,16 +1144,28 @@ RSpec.describe User, type: :model do end describe 'Touching associations on update:' do - subject!(:user) { create(:customer_user) } + subject(:user) { create(:customer_user, organization: organization) } - let!(:organization) { create(:organization) } + let(:organization) { create(:organization) } + let(:other_customer) { create(:customer_user) } - context 'when a customer gets a organization ' do + context 'when basic attributes are updated' do it 'touches its organization' do - expect { user.update(organization: organization) } + expect { user.update(firstname: 'foo') } .to change { organization.reload.updated_at } end end + + context 'when organization has 100+ other members' do + let!(:other_members) { create_list(:user, 100, organization: organization) } + + context 'and basic attributes are updated' do + it 'does not touch its organization' do + expect { user.update(firstname: 'foo') } + .to not_change { organization.reload.updated_at } + end + end + end end describe 'Cti::CallerId syncing:' do diff --git a/spec/system/examples/text_modules_examples.rb b/spec/system/examples/text_modules_examples.rb index 9f27788ec..74a066b01 100644 --- a/spec/system/examples/text_modules_examples.rb +++ b/spec/system/examples/text_modules_examples.rb @@ -7,6 +7,7 @@ RSpec.shared_examples 'text modules' do |path:| let!(:text_module_group2) { create :text_module, groups: [group2] } it 'shows when send ::' do + refresh # workaround to get new created objects from db visit path within(:active_content) do find('select[name="group_id"]').select(1) @@ -40,8 +41,8 @@ RSpec.shared_examples 'text modules' do |path:| user.save! end + refresh # workaround to get changed settings from db visit path - within(:active_content) do find('select[name="group_id"]').select(group1.name) find(:richtext).send_keys('::') diff --git a/test/unit/session_basic_test.rb b/test/unit/session_basic_test.rb index e96c1b8d0..cb0e47337 100644 --- a/test/unit/session_basic_test.rb +++ b/test/unit/session_basic_test.rb @@ -54,107 +54,6 @@ class SessionBasicTest < ActiveSupport::TestCase end - test 'c collections group' do - require 'sessions/backend/collections/group.rb' - - # create users - roles = Role.where(name: ['Agent']) - groups = Group.all - - agent1 = User.create_or_update( - login: 'session-collection-agent-1', - firstname: 'Session', - lastname: 'Agent 1', - email: 'session-collection-agent1@example.com', - password: 'agentpw', - active: true, - roles: roles, - groups: groups, - updated_by_id: 1, - created_by_id: 1, - ) - - collection_client1 = Sessions::Backend::Collections::Group.new(agent1, {}, false, '123-1', 3) - collection_client2 = Sessions::Backend::Collections::Group.new(agent1, {}, false, '234-2', 3) - - # get whole collections - result1 = collection_client1.push - assert(result1.present?, 'check collections') - sleep 0.6 - result2 = collection_client2.push - assert(result2.present?, 'check collections') - assert_equal(result1, result2, 'check collections') - - # next check should be empty - result1 = collection_client1.push - assert_not(result1, 'check collections - recall') - travel 1.second - result2 = collection_client2.push - assert_not(result2, 'check collections - recall') - - # change collection - group = Group.first - travel 4.seconds - group.touch - travel 4.seconds - - # get whole collections - result1 = collection_client1.push - assert(result1.present?, 'check collections - after touch') - - result2 = collection_client2.push - assert(result2.present?, 'check collections - after touch') - assert_equal(result1, result2, 'check collections') - - # check again after touch - result1 = collection_client1.push - assert_nil(result1, 'check collections - after touch - recall') - result2 = collection_client2.push - assert_nil(result2, 'check collections - after touch - recall') - - # change collection - group = Group.create!( - name: "SomeGroup::#{rand(999_999)}", - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - travel 4.seconds - - # get whole collections - result1 = collection_client1.push - assert(result1.present?, 'check collections - after create') - result2 = collection_client2.push - assert(result2.present?, 'check collections - after create') - assert_equal(result1, result2, 'check collections') - - # check again after create - travel 4.seconds - result1 = collection_client1.push - assert_nil(result1, 'check collections - after create - recall') - result2 = collection_client2.push - assert_nil(result2, 'check collections - after create - recall') - - # change collection - group.destroy - travel 4.seconds - - # get whole collections - result1 = collection_client1.push - assert(result1.present?, 'check collections - after destroy') - result2 = collection_client2.push - assert(result2.present?, 'check collections - after destroy') - assert_equal(result1, result2, 'check collections') - - # check again after destroy - travel 4.seconds - result1 = collection_client1.push - assert_nil(result1, 'check collections - after destroy - recall') - result2 = collection_client2.push - assert_nil(result2, 'check collections - after destroy - recall') - travel_back - end - test 'c activity stream' do # create users @@ -217,57 +116,4 @@ class SessionBasicTest < ActiveSupport::TestCase travel_back end - test 'c ticket_create' do - - # create users - roles = Role.where(name: %w[Agent Admin]) - groups = Group.all - - agent1 = User.create_or_update( - login: 'ticket_create-agent-1', - firstname: 'Session', - lastname: "ticket_create #{rand(99_999)}", - email: 'ticket_create-agent1@example.com', - password: 'agentpw', - active: true, - roles: roles, - groups: groups, - updated_by_id: 1, - created_by_id: 1, - ) - - ticket_create_client1 = Sessions::Backend::TicketCreate.new(agent1, {}, false, '123-1', 3) - - # get as stream - result1 = ticket_create_client1.push - assert(result1, 'check ticket_create') - travel 1.second - - # next check should be empty - result1 = ticket_create_client1.push - assert_not(result1, 'check ticket_create - recall') - - # next check should be empty - travel 1.second - result1 = ticket_create_client1.push - assert_not(result1, 'check ticket_create - recall 2') - - Group.create!( - name: "SomeTicketCreateGroup::#{rand(999_999)}", - active: true, - updated_by_id: 1, - created_by_id: 1, - ) - groups = Group.all - agent1.groups = groups - agent1.save! - - travel 4.seconds - - # get as stream - result1 = ticket_create_client1.push - assert(result1, 'check ticket_create - recall 3') - travel_back - end - end diff --git a/test/unit/session_collections_test.rb b/test/unit/session_collections_test.rb deleted file mode 100644 index 6e544e921..000000000 --- a/test/unit/session_collections_test.rb +++ /dev/null @@ -1,221 +0,0 @@ -require 'test_helper' - -class SessionCollectionsTest < ActiveSupport::TestCase - - test 'a collections' do - - UserInfo.current_user_id = 1 - - # create users - roles = Role.where(name: %w[Agent Admin]) - groups = Group.all - - agent1 = User.create_or_update( - login: 'session-collections-agent-1', - firstname: 'Session', - lastname: 'collections 1', - email: 'session-collections-agent-1@example.com', - password: 'agentpw', - organization_id: nil, - active: true, - roles: roles, - groups: groups, - ) - agent1.save! - - roles = Role.where(name: ['Agent']) - groups = Group.all - - agent2 = User.create_or_update( - login: 'session-collections-agent-2', - firstname: 'Session', - lastname: 'collections 2', - email: 'session-collections-agent-2@example.com', - password: 'agentpw', - organization_id: nil, - active: true, - roles: roles, - groups: groups, - ) - agent2.save! - - roles = Role.where(name: ['Customer']) - customer1 = User.create_or_update( - login: 'session-collections-customer-1', - firstname: 'Session', - lastname: 'collections 2', - email: 'session-collections-customer-1@example.com', - password: 'customerpw', - organization_id: nil, - active: true, - roles: roles, - ) - customer1.save! - collection_client1 = Sessions::Backend::Collections.new(agent1, {}, nil, 'aaa-1', 2) - collection_client2 = Sessions::Backend::Collections.new(agent2, {}, nil, 'bbb-2', 2) - collection_client3 = Sessions::Backend::Collections.new(customer1, {}, nil, 'ccc-2', 2) - - # get whole collections - result1 = collection_client1.push - assert(result1, 'check collections') - assert(check_if_collection_exists(result1, :Group), 'check collections - after init') - assert(check_if_collection_exists(result1, :Role), 'check collections - after init') - assert(check_if_collection_exists(result1, :Signature), 'check collections - after init') - assert(check_if_collection_exists(result1, :EmailAddress), 'check collections - after init') - travel 1.second - result2 = collection_client2.push - assert(result2, 'check collections') - assert(check_if_collection_exists(result2, :Group), 'check collections - after init') - assert(check_if_collection_exists(result2, :Role), 'check collections - after init') - assert(check_if_collection_exists(result2, :Signature), 'check collections - after init') - assert(check_if_collection_exists(result2, :EmailAddress), 'check collections - after init') - - assert_equal(result1.length, result2.length, 'check collections') - assert_equal(result1[0], result2[0], 'check collections') - assert_equal(result1[1], result2[1], 'check collections') - assert_equal(result1[2], result2[2], 'check collections') - assert_equal(result1[3], result2[3], 'check collections') - assert_equal(result1[4], result2[4], 'check collections') - assert_equal(result1[5], result2[5], 'check collections') - assert_equal(result1[6], result2[6], 'check collections') - assert_equal(result1[7], result2[7], 'check collections') - assert_equal(result1[8], result2[8], 'check collections') - assert_equal(result1[9], result2[9], 'check collections') - - assert_equal(result1, result2, 'check collections') - - result3 = collection_client3.push - assert(result3, 'check collections') - assert(check_if_collection_exists(result3, :Group), 'check collections - after init') - assert(check_if_collection_exists(result3, :Role), 'check collections - after init') - assert_not(check_if_collection_exists(result3, :Signature), 'check collections - after init') - assert_not(check_if_collection_exists(result3, :EmailAddress), 'check collections - after init') - - # next check should be empty - result1 = collection_client1.push - assert(result1.blank?, 'check collections - recall') - travel 0.4.seconds - result2 = collection_client2.push - assert(result2.blank?, 'check collections - recall') - result3 = collection_client3.push - assert(result3.blank?, 'check collections - recall') - - # change collection - group = Group.first - travel 6.seconds - group.touch - travel 6.seconds - - # get whole collections - result1 = collection_client1.push - - assert(result1, 'check collections - after touch') - assert(check_if_collection_exists(result1, :Group), 'check collections - after touch') - travel 0.1.seconds - result2 = collection_client2.push - assert(result2, 'check collections - after touch') - assert(check_if_collection_exists(result2, :Group), 'check collections - after touch') - result3 = collection_client3.push - assert(result3, 'check collections - after touch') - assert(check_if_collection_exists(result3, :Group), 'check collections - after touch') - - # next check should be empty - travel 0.5.seconds - result1 = collection_client1.push - assert(result1.blank?, 'check collections - recall') - result2 = collection_client2.push - assert(result2.blank?, 'check collections - recall') - result3 = collection_client3.push - assert(result3.blank?, 'check collections - recall') - - travel 10.seconds - Sessions.destroy_idle_sessions(3) - - travel_back - end - - def check_if_collection_exists(results, collection, attributes = nil) - results.each do |result| - next if !result - next if !result[:collection] - next if !result[:collection][collection] - - # check just if collection exists - return true if !attributes - - # check if objetc with attributes in collection exists - result[:collection][collection].each do |item| - match_all = true - attributes.each do |key, value| - - # sort array, database result maybe unsorted - item_attributes = item[ key.to_s ] - if item[ key.to_s ].class == Array - item_attributes.sort! - end - if value.class == Array - value.sort! - end - - # compare values - if item_attributes != value - #p "FAILED: #{key} -> #{item_attributes.inspect} vs. #{value.inspect}" - match_all = false - end - end - return true if match_all - end - end - nil - end - - test 'b assets' do - roles = Role.where(name: %w[Agent Admin]) - groups = Group.all.order(id: :asc) - - UserInfo.current_user_id = 2 - agent1 = User.create_or_update( - login: "sessions-assets-1-#{rand(99_999)}", - firstname: 'Session', - lastname: "sessions assets #{rand(99_999)}", - email: 'sessions-assets1@example.com', - password: 'agentpw', - active: true, - roles: roles, - groups: groups, - ) - assert(agent1.save!, 'create/update agent1') - - assets = {} - client1 = Sessions::Backend::Collections::Group.new(agent1, assets, false, '123-1', 4) - data = client1.push - assert_equal(data[:collection][:Group][0]['id'], groups[0].id) - assert(data[:assets][:Group][groups.first.id]) - travel 10.seconds - - client1 = Sessions::Backend::Collections::Group.new(agent1, assets, false, '123-1', 4) - data = client1.push - assert_equal(data[:collection][:Group][0]['id'], groups[0].id) - assert(data[:assets]) - assert_not(data[:assets][:Group]) - - travel 125.minutes - - client1 = Sessions::Backend::Collections::Group.new(agent1, assets, false, '123-1', 4) - data = client1.push - assert_equal(data[:collection][:Group][0]['id'], groups[0].id) - assert(data[:assets][:Group][groups.first.id]) - - travel 2.minutes - client1 = Sessions::Backend::Collections::Group.new(agent1, assets, false, '123-1', 4) - data = client1.push - assert_equal(data[:collection][:Group][0]['id'], groups[0].id) - assert_nil(data[:assets][:Group]) - - travel 10.seconds - Sessions.destroy_idle_sessions(3) - - travel_back - end - -end diff --git a/test/unit/session_enhanced_test.rb b/test/unit/session_enhanced_test.rb index d4a22461c..71cf3a294 100644 --- a/test/unit/session_enhanced_test.rb +++ b/test/unit/session_enhanced_test.rb @@ -249,58 +249,6 @@ class SessionEnhancedTest < ActiveSupport::TestCase assert(Sessions.session_exists?(client_id2), 'check if session exists') assert(Sessions.session_exists?(client_id3), 'check if session exists') - travel 8.seconds - sleep 8 - - # check collections - collections = { - 'Group' => true, - 'User' => nil, - } - assert_if_collection_reset_message_exists(client_id1_0, collections, 'init') - assert_if_collection_reset_message_exists(client_id1_1, collections, 'init') - assert_if_collection_reset_message_exists(client_id2, collections, 'init') - assert_if_collection_reset_message_exists(client_id3, collections, 'init') - - collections = { - 'Group' => nil, - 'User' => nil, - } - assert_if_collection_reset_message_exists(client_id1_0, collections, 'init2') - assert_if_collection_reset_message_exists(client_id1_1, collections, 'init2') - assert_if_collection_reset_message_exists(client_id2, collections, 'init2') - assert_if_collection_reset_message_exists(client_id3, collections, 'init2') - - travel 8.seconds - sleep 8 - - collections = { - 'Group' => nil, - 'User' => nil, - } - assert_if_collection_reset_message_exists(client_id1_0, collections, 'init3') - assert_if_collection_reset_message_exists(client_id1_1, collections, 'init3') - assert_if_collection_reset_message_exists(client_id2, collections, 'init3') - assert_if_collection_reset_message_exists(client_id3, collections, 'init3') - - # change collection - group = Group.first - travel 4.seconds - group.touch - - travel 12.seconds - sleep 12 - - # check collections - collections = { - 'Group' => true, - 'User' => nil, - } - assert_if_collection_reset_message_exists(client_id1_0, collections, 'update') - assert_if_collection_reset_message_exists(client_id1_1, collections, 'update') - assert_if_collection_reset_message_exists(client_id2, collections, 'update') - assert_if_collection_reset_message_exists(client_id3, collections, 'update') - # check if session still exists after idle cleanup travel 10.seconds Sessions.destroy_idle_sessions(2) @@ -318,30 +266,4 @@ class SessionEnhancedTest < ActiveSupport::TestCase travel_back end - def assert_if_collection_reset_message_exists(client_id, collections_orig, type) - messages = Sessions.queue(client_id) - #puts "cid: #{client_id}" - #puts "m: #{messages.inspect}" - collections_result = {} - messages.each do |message| - #puts "" - #puts "message: #{message.inspect}" - next if message['event'] != 'resetCollection' - #puts "rc: " - next if !message['data'] - - message['data'].each_key do |key| - #puts "rc: #{key}" - collections_result[key] = true - end - end - #puts "c: #{collections_result.inspect}" - collections_orig.each_key do |key| - if collections_orig[key].nil? - assert_nil(collections_result[key], "collection message for #{key} #{type}-check (client_id #{client_id})") - else - assert_equal(collections_orig[key], collections_result[key], "collection message for #{key} #{type}-check (client_id #{client_id})") - end - end - end end