Browse Source

Refactoring: Migrate history_test to RSpec

Ryan Lue 5 years ago
parent
commit
4a1477b1ff

+ 34 - 67
app/models/history.rb

@@ -149,73 +149,54 @@ returns
 =end
 
   def self.list(requested_object, requested_object_id, related_history_object = nil, assets = nil)
-    if related_history_object.blank?
-      history_object = object_lookup(requested_object)
-      history = History.where(history_object_id: history_object.id)
-                       .where(o_id: requested_object_id)
-                       .order(created_at: :asc)
-    else
-      history_object_requested = object_lookup(requested_object)
-      history_object_related   = object_lookup(related_history_object)
-      history = History.where(
-        '((history_object_id = ? AND o_id = ?) OR (history_object_id = ? AND related_o_id = ? ))',
-        history_object_requested.id,
-        requested_object_id,
-        history_object_related.id,
-        requested_object_id,
+    histories = History.where(
+      history_object_id: object_lookup(requested_object).id,
+      o_id:              requested_object_id
+    )
+
+    if related_history_object.present?
+      histories = histories.or(
+        History.where(
+          history_object_id: object_lookup(related_history_object).id,
+          related_o_id:      requested_object_id
+        )
       )
-                       .order(created_at: :asc)
     end
-    asset_list = {}
-    list = []
-    history.each do |item|
 
-      if assets
-        asset_list = item.assets(asset_list)
-      end
+    histories = histories.order(:created_at)
 
-      data = item.attributes
-      data['object']    = object_lookup_id(data['history_object_id']).name
-      data['type']      = type_lookup_id(data['history_type_id']).name
-      data.delete('history_object_id')
-      data.delete('history_type_id')
+    list = histories.map(&:attributes).each do |data|
+      data['object'] = History::Object.lookup(id: data.delete('history_object_id'))&.name
+      data['type']   = History::Type.lookup(id: data.delete('history_type_id'))&.name
 
       if data['history_attribute_id']
-        data['attribute'] = attribute_lookup_id(data['history_attribute_id']).name
+        data['attribute'] = History::Attribute.lookup(id: data.delete('history_attribute_id'))&.name
+      end
+
+      if data['related_history_object_id']
+        data['related_object'] = History::Object.lookup(id: data.delete('related_history_object_id'))&.name
       end
-      data.delete('history_attribute_id')
 
       data.delete('updated_at')
+      data.delete('related_o_id') if data['related_o_id'].nil?
+
       if data['id_to'].nil? && data['id_from'].nil?
-        data.delete('id_to')
         data.delete('id_from')
+        data.delete('id_to')
       end
+
       if data['value_to'].nil? && data['value_from'].nil?
-        data.delete('value_to')
         data.delete('value_from')
+        data.delete('value_to')
       end
-      if !data['related_history_object_id'].nil?
-        data['related_object'] = object_lookup_id(data['related_history_object_id']).name
-      end
-      data.delete('related_history_object_id')
-
-      if data['related_o_id'].nil?
-        data.delete('related_o_id')
-      end
-
-      list.push data
     end
-    if assets
-      return {
-        list:   list,
-        assets: asset_list,
-      }
-    end
-    list
-  end
 
-  def self.type_lookup_id(id)
-    History::Type.lookup(id: id)
+    return list if !assets
+
+    {
+      list:   list,
+      assets: histories.reduce({}) { |memo, obj| obj.assets(memo) }
+    }
   end
 
   def self.type_lookup(name)
@@ -227,10 +208,6 @@ returns
     History::Type.create!(name: name)
   end
 
-  def self.object_lookup_id(id)
-    History::Object.lookup(id: id)
-  end
-
   def self.object_lookup(name)
     # lookup
     history_object = History::Object.lookup(name: name)
@@ -240,10 +217,6 @@ returns
     History::Object.create!(name: name)
   end
 
-  def self.attribute_lookup_id(id)
-    History::Attribute.lookup(id: id)
-  end
-
   def self.attribute_lookup(name)
     # lookup
     history_attribute = History::Attribute.lookup(name: name)
@@ -253,13 +226,7 @@ returns
     History::Attribute.create!(name: name)
   end
 
-  class Object < ApplicationModel
-  end
-
-  class Type < ApplicationModel
-  end
-
-  class Attribute < ApplicationModel
-  end
-
+  class Object < ApplicationModel; end
+  class Type < ApplicationModel; end
+  class Attribute < ApplicationModel; end
 end

+ 123 - 0
spec/models/concerns/has_history_examples.rb

@@ -0,0 +1,123 @@
+RSpec.shared_examples 'HasHistory' do |history_relation_object: nil|
+  describe 'auto-creation of history records' do
+    let(:histories) { History.where(history_object_id: History::Object.find_by(name: described_class.name)) }
+
+    context 'on creation' do
+      it 'creates a History record for it' do
+        expect { subject }.to change(histories, :count).by(1)
+        expect(histories.last.history_type.name).to eq('created')
+      end
+    end
+
+    context 'on update' do
+      let(:histories) do
+        History.where(history_object_id:    History::Object.lookup(name: described_class.name).id,
+                      history_type_id:      History::Type.lookup(name: 'updated').id,
+                      history_attribute_id: History::Attribute.find_or_create_by(name: attribute).id)
+      end
+
+      let!(:old_value) { subject.send(attribute) }
+
+      shared_examples 'attribute update' do
+        it 'creates a History record for it' do
+          expect { subject.update(attribute => new_value) }.to change(histories, :count).by(1)
+          expect(histories.last.attributes).to include(attributes)
+        end
+      end
+
+      describe 'of #active' do
+        let(:attribute) { 'active' }
+        let(:new_value) { !subject.active }
+        let(:attributes) { { 'value_from' => old_value.to_s, 'value_to' => new_value.to_s } }
+
+        include_examples 'attribute update' if described_class.attribute_names.include?('active')
+      end
+
+      describe 'of #body' do
+        let(:attribute) { 'body' }
+        let(:new_value) { 'Lorem ipsum dolor' }
+        let(:attributes) { { 'value_from' => old_value, 'value_to' => new_value } }
+
+        include_examples 'attribute update' if described_class.attribute_names.include?('body')
+      end
+
+      describe 'of #email' do
+        let(:attribute) { 'email' }
+        let(:new_value) { Faker::Internet.email }
+        let(:attributes) { { 'value_from' => old_value, 'value_to' => new_value } }
+
+        include_examples 'attribute update' if described_class.attribute_names.include?('email')
+      end
+
+      describe 'of #lastname' do
+        let(:attribute) { 'lastname' }
+        let(:new_value) { 'Foo' }
+        let(:attributes) { { 'value_from' => old_value, 'value_to' => new_value } }
+
+        include_examples 'attribute update' if described_class.attribute_names.include?('lastname')
+      end
+
+      describe 'of #name' do
+        let(:attribute) { 'name' }
+        let(:new_value) { 'Foo' }
+        let(:attributes) { { 'value_from' => old_value, 'value_to' => new_value } }
+
+        include_examples 'attribute update' if described_class.attribute_names.include?('name')
+      end
+
+      describe 'of #state' do
+        let(:attribute) { 'state' }
+        let(:new_value) { state_class.where.not(id: old_value.id).first }
+        let(:state_class) { "#{described_class.name}::State".constantize }
+        let(:attributes) { { 'value_from' => old_value.name, 'value_to' => new_value.name } }
+
+        include_examples 'attribute update' if described_class.attribute_names.include?('state_id')
+      end
+
+      describe 'of #title' do
+        let(:attribute) { 'title' }
+        let(:new_value) { 'foo' }
+        let(:attributes) { { 'value_from' => old_value, 'value_to' => new_value } }
+
+        include_examples 'attribute update' if described_class.attribute_names.include?('title')
+      end
+
+      context 'when validations or callbacks prevent update' do
+        shared_examples 'failed attribute update' do
+          it 'does not create a History record for it' do
+            expect { subject.update(attribute => new_value) }.not_to change(histories, :count)
+          end
+        end
+
+        describe 'of #owner' do
+          let(:attribute) { 'owner' }
+          let(:new_value) { create(:customer_user) }  # Ticket#owner is restricted to active agents of the same group
+
+          include_examples 'failed attribute update' if described_class.attribute_names.include?('owner_id')
+        end
+      end
+    end
+  end
+
+  describe '#history_get' do
+    context 'without "full" flag' do
+      it 'delegates to History.list for self' do
+        expect(History).to receive(:list).with(described_class.name, subject.id, history_relation_object)
+
+        subject.history_get
+      end
+    end
+
+    context 'with "full" flag' do
+      it 'returns a hash including History.list for self' do
+        expect(subject.history_get(true))
+          .to include(history: History.list(described_class.name, subject.id, history_relation_object))
+      end
+
+      it 'returns a hash including FE assets of self and related objects' do
+        expect(subject.history_get(true))
+          .to include(assets: hash_including(subject.assets({})))
+      end
+    end
+  end
+end

+ 184 - 0
spec/models/history_spec.rb

@@ -5,4 +5,188 @@ require 'models/concerns/can_be_imported_examples'
 RSpec.describe History, type: :model do
   it_behaves_like 'ApplicationModel', can_assets: { own_attributes: false }
   it_behaves_like 'CanBeImported'
+
+  describe '.list' do
+    context 'when given an object with no histories' do
+      let!(:object) { create(:'cti/log') }
+
+      it 'returns an empty array' do
+        expect(History.list(object.class.name, object.id))
+          .to be_an(Array).and be_empty
+      end
+    end
+
+    context 'when given an object with histories' do
+      context 'and called without "related_history_object" argument' do
+        let!(:object) { create(:user) }
+
+        before { object.update(email: 'foo@example.com') }
+
+        context 'or "assets" flag' do
+          let(:list) { History.list(object.class.name, object.id) }
+
+          it 'returns an array of attribute hashes for those histories' do
+            expect(list).to match_array(
+              [
+                hash_including(
+                  'o_id'   => object.id,
+                ),
+                hash_including(
+                  'o_id'     => object.id,
+                  'value_to' => 'foo@example.com',
+                )
+              ]
+            )
+          end
+
+          it 'replaces *_id attributes with the corresponding association #name' do
+            expect(list.first)
+              .to not_include('history_object_id', 'history_type_id')
+              .and include(
+                'object' => object.class.name,
+                'type'   => 'created',
+              )
+
+            expect(list.second)
+              .to not_include('history_object_id', 'history_type_id', 'history_attribute_id')
+              .and include(
+                'object'    => object.class.name,
+                'type'      => 'updated',
+                'attribute' => 'email',
+              )
+          end
+        end
+
+        context 'but with "assets" flag' do
+          let(:list) { History.list(object.class.name, object.id, nil, true) }
+          let(:matching_histories) do
+            History.where(
+              o_id:              object.id,
+              history_object_id: History::Object.lookup(name: object.class.name).id
+            )
+          end
+
+          it 'returns a hash including an array of history attribute hashes' do
+            expect(list).to include(
+              list: [
+                hash_including(
+                  'o_id'   => object.id,
+                  'object' => object.class.name,
+                  'type'   => 'created',
+                ),
+                hash_including(
+                  'o_id'      => object.id,
+                  'object'    => object.class.name,
+                  'type'      => 'updated',
+                  'attribute' => 'email',
+                  'value_to'  => 'foo@example.com',
+                )
+              ]
+            )
+          end
+
+          it 'returns a hash including each history record’s FE assets' do
+            expect(list).to include(
+              assets: matching_histories.reduce({}) { |assets, h| h.assets(assets) }
+            )
+          end
+        end
+      end
+
+      context 'with "related_history_object" argument' do
+        let!(:object) { related_object.ticket }
+        let!(:related_object) { create(:ticket_article, internal: true) }  # MUST be internal, or else callbacks will create additional histories
+
+        before { object.update(title: 'Lorem ipsum dolor') }
+
+        context 'but no "assets" flag' do
+          let(:list) { History.list(object.class.name, object.id, 'Ticket::Article') }
+
+          it 'returns an array of attribute hashes for those histories' do
+            expect(list).to match_array(
+              [
+                hash_including(
+                  'o_id'   => object.id,
+                ),
+                hash_including(
+                  'o_id'   => related_object.id,
+                ),
+                hash_including(
+                  'o_id'     => object.id,
+                  'value_to' => 'Lorem ipsum dolor',
+                )
+              ]
+            )
+          end
+
+          it 'replaces *_id attributes with the corresponding association #name' do
+            expect(list.first)
+              .to not_include('history_object_id', 'history_type_id')
+              .and include(
+                'object' => object.class.name,
+                'type'   => 'created',
+              )
+
+            expect(list.second)
+              .to not_include('history_object_id', 'history_type_id')
+              .and include(
+                'object' => related_object.class.name,
+                'type'   => 'created',
+              )
+
+            expect(list.third)
+              .to not_include('history_object_id', 'history_type_id', 'history_attribute_id')
+              .and include(
+                'object'    => object.class.name,
+                'type'      => 'updated',
+                'attribute' => 'title',
+              )
+          end
+        end
+
+        context 'and "assets" flag' do
+          let(:list) { History.list(object.class.name, object.id, 'Ticket::Article', true) }
+          let(:matching_histories) do
+            History.where(
+              o_id:              object.id,
+              history_object_id: History::Object.lookup(name: object.class.name).id
+            ) + History.where(
+              o_id:              related_object.id,
+              history_object_id: History::Object.lookup(name: related_object.class.name).id
+            )
+          end
+
+          it 'returns a hash including an array of history attribute hashes' do
+            expect(list).to include(
+              list: [
+                hash_including(
+                  'o_id'   => object.id,
+                  'object' => object.class.name,
+                  'type'   => 'created',
+                ),
+                hash_including(
+                  'o_id'   => related_object.id,
+                  'object' => related_object.class.name,
+                  'type'   => 'created',
+                ),
+                hash_including(
+                  'o_id'      => object.id,
+                  'object'    => object.class.name,
+                  'type'      => 'updated',
+                  'attribute' => 'title',
+                  'value_to'  => 'Lorem ipsum dolor',
+                )
+              ]
+            )
+          end
+
+          it 'returns a hash including each history record’s FE assets' do
+            expect(list).to include(
+              assets: matching_histories.reduce({}) { |assets, h| h.assets(assets) }
+            )
+          end
+        end
+      end
+    end
+  end
 end

+ 2 - 0
spec/models/organization_spec.rb

@@ -1,6 +1,7 @@
 require 'rails_helper'
 require 'models/application_model_examples'
 require 'models/concerns/can_lookup_examples'
+require 'models/concerns/has_history_examples'
 require 'models/concerns/has_search_index_backend_examples'
 require 'models/concerns/has_xss_sanitized_note_examples'
 require 'models/concerns/has_object_manager_attributes_validation_examples'
@@ -8,6 +9,7 @@ require 'models/concerns/has_object_manager_attributes_validation_examples'
 RSpec.describe Organization, type: :model do
   it_behaves_like 'ApplicationModel', can_assets: { associations: :members }
   it_behaves_like 'CanLookup'
+  it_behaves_like 'HasHistory'
   it_behaves_like 'HasSearchIndexBackend', indexed_factory: :organization
   it_behaves_like 'HasXssSanitizedNote', model_factory: :organization
   it_behaves_like 'HasObjectManagerAttributesValidation'

+ 2 - 0
spec/models/ticket/article_spec.rb

@@ -1,11 +1,13 @@
 require 'rails_helper'
 require 'models/application_model_examples'
 require 'models/concerns/can_be_imported_examples'
+require 'models/concerns/has_history_examples'
 require 'models/concerns/has_object_manager_attributes_validation_examples'
 
 RSpec.describe Ticket::Article, type: :model do
   it_behaves_like 'ApplicationModel'
   it_behaves_like 'CanBeImported'
+  it_behaves_like 'HasHistory'
   it_behaves_like 'HasObjectManagerAttributesValidation'
 
   subject(:article) { create(:ticket_article) }

+ 2 - 0
spec/models/ticket_spec.rb

@@ -2,6 +2,7 @@ require 'rails_helper'
 require 'models/application_model_examples'
 require 'models/concerns/can_be_imported_examples'
 require 'models/concerns/can_lookup_examples'
+require 'models/concerns/has_history_examples'
 require 'models/concerns/has_xss_sanitized_note_examples'
 require 'models/concerns/has_object_manager_attributes_validation_examples'
 
@@ -9,6 +10,7 @@ RSpec.describe Ticket, type: :model do
   it_behaves_like 'ApplicationModel'
   it_behaves_like 'CanBeImported'
   it_behaves_like 'CanLookup'
+  it_behaves_like 'HasHistory', history_relation_object: 'Ticket::Article'
   it_behaves_like 'HasXssSanitizedNote', model_factory: :ticket
   it_behaves_like 'HasObjectManagerAttributesValidation'
 

+ 2 - 0
spec/models/user_spec.rb

@@ -1,6 +1,7 @@
 require 'rails_helper'
 require 'models/application_model_examples'
 require 'models/concerns/has_groups_examples'
+require 'models/concerns/has_history_examples'
 require 'models/concerns/has_roles_examples'
 require 'models/concerns/has_groups_permissions_examples'
 require 'models/concerns/has_xss_sanitized_note_examples'
@@ -17,6 +18,7 @@ RSpec.describe User, type: :model do
 
   it_behaves_like 'ApplicationModel', can_assets: { associations: :organization }
   it_behaves_like 'HasGroups', group_access_factory: :agent_user
+  it_behaves_like 'HasHistory'
   it_behaves_like 'HasRoles', group_access_factory: :agent_user
   it_behaves_like 'HasXssSanitizedNote', model_factory: :user
   it_behaves_like 'HasGroups and Permissions', group_access_no_permission_factory: :user

+ 0 - 432
test/unit/history_test.rb

@@ -1,432 +0,0 @@
-require 'test_helper'
-
-class HistoryTest < ActiveSupport::TestCase
-
-  test 'ticket' do
-    current_user = User.lookup(email: 'nicole.braun@zammad.org')
-    tests = [
-
-      # test 1
-      {
-        ticket_create: {
-          ticket:  {
-            group_id:      Group.lookup(name: 'Users').id,
-            customer_id:   current_user.id,
-            owner_id:      User.lookup(login: '-').id,
-            title:         'Unit Test 1 (äöüß)!',
-            state_id:      Ticket::State.lookup(name: 'new').id,
-            priority_id:   Ticket::Priority.lookup(name: '2 normal').id,
-            updated_by_id: current_user.id,
-            created_by_id: current_user.id,
-          },
-          article: {
-            updated_by_id: current_user.id,
-            created_by_id: current_user.id,
-            type_id:       Ticket::Article::Type.lookup(name: 'phone').id,
-            sender_id:     Ticket::Article::Sender.lookup(name: 'Customer').id,
-            from:          'Unit Test <unittest@example.com>',
-            body:          'Unit Test 123',
-            internal:      false,
-          },
-        },
-        ticket_update: {
-          ticket: {
-            title:       'Unit Test 1 (äöüß) - update!',
-            state_id:    Ticket::State.lookup(name: 'open').id,
-            priority_id: Ticket::Priority.lookup(name: '1 low').id,
-          },
-        },
-        history_check: [
-          {
-            result:         true,
-            history_object: 'Ticket',
-            history_type:   'created',
-          },
-          {
-            result:            true,
-            history_object:    'Ticket',
-            history_type:      'updated',
-            history_attribute: 'title',
-            value_from:        'Unit Test 1 (äöüß)!',
-            value_to:          'Unit Test 1 (äöüß) - update!',
-          },
-          {
-            result:            true,
-            history_object:    'Ticket',
-            history_type:      'updated',
-            history_attribute: 'state',
-            value_from:        'new',
-            value_to:          'open',
-            id_from:           Ticket::State.lookup(name: 'new').id,
-            id_to:             Ticket::State.lookup(name: 'open').id,
-          },
-          {
-            result:         true,
-            history_object: 'Ticket::Article',
-            history_type:   'created',
-          },
-          {
-            result:         false,
-            history_object: 'User',
-            history_type:   'updated',
-          },
-        ]
-      },
-
-      # test 2
-      {
-        ticket_create: {
-          ticket:  {
-            group_id:      Group.lookup(name: 'Users').id,
-            customer_id:   current_user.id,
-            owner_id:      User.lookup(login: '-').id,
-            title:         'Unit Test 2 (äöüß)!',
-            state_id:      Ticket::State.lookup(name: 'new').id,
-            priority_id:   Ticket::Priority.lookup(name: '2 normal').id,
-            updated_by_id: current_user.id,
-            created_by_id: current_user.id,
-          },
-          article: {
-            created_by_id: current_user.id,
-            updated_by_id: current_user.id,
-            type_id:       Ticket::Article::Type.lookup(name: 'phone').id,
-            sender_id:     Ticket::Article::Sender.lookup(name: 'Customer').id,
-            from:          'Unit Test <unittest@example.com>',
-            body:          'Unit Test 123',
-            internal:      false,
-          },
-        },
-        ticket_update: {
-          ticket:  {
-            title:    'Unit Test 2 (äöüß) - update!',
-            state_id: Ticket::State.lookup(name: 'open').id,
-            owner_id: current_user.id,
-          },
-          article: {
-            body: 'Unit Test 123 - 2',
-          },
-        },
-        history_check: [
-          {
-            result:         true,
-            history_object: 'Ticket',
-            history_type:   'created',
-          },
-          {
-            result:            true,
-            history_object:    'Ticket',
-            history_type:      'updated',
-            history_attribute: 'title',
-            value_from:        'Unit Test 2 (äöüß)!',
-            value_to:          'Unit Test 2 (äöüß) - update!',
-          },
-          {
-            result:            false,
-            history_object:    'Ticket',
-            history_type:      'updated',
-            history_attribute: 'owner',
-            value_from:        '-',
-            value_to:          'Nicole Braun',
-            id_from:           User.lookup(login: '-').id,
-            id_to:             current_user.id,
-          },
-          {
-            result:         true,
-            history_object: 'Ticket::Article',
-            history_type:   'created',
-          },
-          {
-            result:            true,
-            history_object:    'Ticket::Article',
-            history_type:      'updated',
-            history_attribute: 'body',
-            value_from:        'Unit Test 123',
-            value_to:          'Unit Test 123 - 2',
-          },
-        ]
-      },
-    ]
-    tickets = []
-    tests.each do |test|
-
-      ticket = nil
-      article = nil
-
-      # use transaction
-      ActiveRecord::Base.transaction do
-        ticket = Ticket.create!(test[:ticket_create][:ticket])
-        test[:ticket_create][:article][:ticket_id] = ticket.id
-        article = Ticket::Article.create!(test[:ticket_create][:article])
-
-        assert_equal(ticket.class, Ticket)
-        assert_equal(article.class, Ticket::Article)
-
-        # update ticket
-        if test[:ticket_update][:ticket]
-          ticket.update!(test[:ticket_update][:ticket])
-        end
-        if test[:ticket_update][:article]
-          article.update!(test[:ticket_update][:article])
-        end
-      end
-
-      # execute object transaction
-      Observer::Transaction.commit
-
-      # execute background jobs
-      Scheduler.worker(true)
-
-      # remember ticket
-      tickets.push ticket
-
-      # check history
-      history_check(ticket.history_get, test[:history_check])
-    end
-
-    # delete tickets
-    tickets.each(&:destroy!)
-  end
-
-  test 'user' do
-    current_user = User.lookup(email: 'nicole.braun@zammad.org')
-    name = rand(999_999)
-    tests = [
-
-      # test 1
-      {
-        user_create:   {
-          user: {
-            login:         "some_login_test-#{name}",
-            firstname:     'Bob',
-            lastname:      'Smith',
-            email:         "somebody-#{name}@example.com",
-            active:        true,
-            updated_by_id: current_user.id,
-            created_by_id: current_user.id,
-          },
-        },
-        user_update:   {
-          user: {
-            firstname: 'Bob',
-            lastname:  'Master',
-            email:     "master-#{name}@example.com",
-            active:    false,
-          },
-        },
-        history_check: [
-          {
-            result:         true,
-            history_object: 'User',
-            history_type:   'created',
-          },
-          {
-            result:            true,
-            history_object:    'User',
-            history_type:      'updated',
-            history_attribute: 'lastname',
-            value_from:        'Smith',
-            value_to:          'Master',
-          },
-          {
-            result:            true,
-            history_object:    'User',
-            history_type:      'updated',
-            history_attribute: 'email',
-            value_from:        "somebody-#{name}@example.com",
-            value_to:          "master-#{name}@example.com",
-          },
-          {
-            result:            true,
-            history_object:    'User',
-            history_type:      'updated',
-            history_attribute: 'active',
-            value_from:        'true',
-            value_to:          'false',
-          },
-        ],
-      },
-
-    ]
-    users = []
-    tests.each do |test|
-
-      user = nil
-
-      # user transaction
-      ActiveRecord::Base.transaction do
-        user = User.create!(test[:user_create][:user])
-        assert_equal(user.class, User)
-
-        # update user
-        if test[:user_update][:user]
-          test[:user_update][:user][:active] = false
-          user.update!(test[:user_update][:user])
-        end
-      end
-
-      # remember user
-      users.push user
-
-      # check history
-      history_check(user.history_get, test[:history_check])
-    end
-
-    # delete user
-    users.each(&:destroy!)
-  end
-
-  test 'organization' do
-    current_user = User.lookup(email: 'nicole.braun@zammad.org')
-    tests = [
-
-      # test 1
-      {
-        organization_create: {
-          organization: {
-            name:          'Org äöüß',
-            note:          'some note',
-            updated_by_id: current_user.id,
-            created_by_id: current_user.id,
-          },
-        },
-        organization_update: {
-          organization: {
-            name: 'Org 123',
-            note: 'some note',
-          },
-        },
-        history_check:       [
-          {
-            result:         true,
-            history_object: 'Organization',
-            history_type:   'created',
-          },
-          {
-            result:            true,
-            history_object:    'Organization',
-            history_type:      'updated',
-            history_attribute: 'name',
-            value_from:        'Org äöüß',
-            value_to:          'Org 123',
-          },
-        ],
-      },
-    ]
-    organizations = []
-    tests.each do |test|
-
-      organization = nil
-
-      # user transaction
-      ActiveRecord::Base.transaction do
-        organization = Organization.create!(test[:organization_create][:organization])
-        assert_equal(organization.class, Organization)
-
-        # update organization
-        if test[:organization_update][:organization]
-          organization.update!(test[:organization_update][:organization])
-        end
-      end
-
-      # remember user
-      organizations.push organization
-
-      # check history
-      history_check(organization.history_get, test[:history_check])
-    end
-
-    # delete user
-    organizations.each(&:destroy!)
-  end
-
-  test 'ticket assets' do
-    UserInfo.current_user_id = 1
-    agent1 = User.create!(
-      login:     'agent1@example.com',
-      firstname: 'agent',
-      lastname:  '1',
-      email:     'agent1@example.com',
-      password:  'agentpw',
-      active:    true,
-      roles:     Role.where(name: %w[Agent Admin]),
-      groups:    Group.all,
-    )
-    current_user = User.lookup(email: 'nicole.braun@zammad.org')
-    UserInfo.current_user_id = current_user.id
-
-    ticket = Ticket.create!(
-      title:       'test 1',
-      group:       Group.first,
-      customer_id: current_user.id,
-      state:       Ticket::State.lookup(name: 'new'),
-      priority:    Ticket::Priority.lookup(name: '2 normal'),
-    )
-    article = Ticket::Article.create!(
-      ticket_id:  ticket.id,
-      from:       'some_customer_com-1@example.com',
-      to:         'some_zammad_com-1@example.com',
-      subject:    'com test 1',
-      message_id: 'some@id_com_1',
-      body:       'some message 123',
-      internal:   false,
-      sender:     Ticket::Article::Sender.find_by(name: 'Customer'),
-      type:       Ticket::Article::Type.find_by(name: 'email'),
-    )
-
-    # verify if user of history record is in assets
-    UserInfo.current_user_id = agent1.id
-    ticket.state = Ticket::State.find_by(name: 'closed')
-    ticket.save!
-
-    # update updated_by (to not include agent1 in assets by ticket)
-    UserInfo.current_user_id = current_user.id
-    ticket.priority = Ticket::Priority.find_by(name: '3 high')
-    ticket.save!
-
-    history = ticket.history_get(true)
-    assert(history[:assets][:User][current_user.id])
-    assert(history[:assets][:User][agent1.id])
-    assert(history[:assets][:Ticket][ticket.id])
-    assert(history[:assets][:TicketArticle][article.id])
-  end
-
-  def history_check(history_list, history_check)
-    history_check.each do |check_item|
-      match = false
-      history_list.each do |history_item|
-        next if match
-        next if history_item['object'] != check_item[:history_object]
-        next if history_item['type'] != check_item[:history_type]
-
-        if check_item[:history_attribute]
-          next if check_item[:history_attribute] != history_item['attribute']
-        end
-        match = true
-        if history_item['type'] == check_item[:history_type]
-          assert(true, "History type #{history_item['type']} found!")
-        end
-        if check_item[:history_attribute]
-          assert_equal(check_item[:history_attribute], history_item['attribute'], "check history attribute #{check_item[:history_attribute]}")
-        end
-        if check_item[:value_from]
-          assert_equal(check_item[:value_from], history_item['value_from'], "check history :value_from #{history_item['value_from']} ok")
-        end
-        if check_item[:value_to]
-          assert_equal(check_item[:value_to], history_item['value_to'], "check history :value_to #{history_item['value_to']} ok")
-        end
-        if check_item[:id_from]
-          assert_equal(check_item[:id_from], history_item['id_from'], "check history :id_from #{history_item['id_from']} ok")
-        end
-        if check_item[:id_to]
-          assert_equal(check_item[:id_to], history_item['id_to'], "check history :id_to #{history_item['id_to']} ok")
-        end
-      end
-      if check_item[:result]
-        assert(match, "history check not matched! #{check_item.inspect}")
-      else
-        assert_not(match, "history check matched but should not! #{check_item.inspect}")
-      end
-    end
-  end
-
-end