diff --git a/spec/models/organization_spec.rb b/spec/models/organization_spec.rb index fc5cd1f02..4baa7a7cf 100644 --- a/spec/models/organization_spec.rb +++ b/spec/models/organization_spec.rb @@ -12,12 +12,58 @@ RSpec.describe Organization, type: :model do it_behaves_like 'HasXssSanitizedNote', model_factory: :organization it_behaves_like 'HasObjectManagerAttributesValidation' - describe '.where_or_cis' do - it 'finds instance by querying multiple attributes case insensitive' do - # search for Zammad Foundation - organizations = described_class.where_or_cis(%i[name note], '%zammad%') - expect(organizations).not_to be_blank + subject(:organization) { create(:organization) } + + describe 'Class methods:' do + describe '.where_or_cis' do + it 'finds instance by querying multiple attributes case insensitive' do + # search for Zammad Foundation + organizations = described_class.where_or_cis(%i[name note], '%zammad%') + expect(organizations).not_to be_blank + end end end + describe 'Callbacks, Observers, & Async Transactions -' do + describe 'Touching associations on update:' do + let!(:member) { create(:customer_user, organization: organization) } + let!(:member_ticket) { create(:ticket, customer: member) } + + context 'when basic attributes are updated' do + it 'touches its members and their tickets' do + expect { organization.update(name: 'foo') } + .to change { member.reload.updated_at } + .and change { member_ticket.reload.updated_at } + end + end + + context 'when member associations are added' do + let(:user) { create(:customer_user) } + + it 'is touched, and touches its other members (but not their tickets)' do + expect { organization.members.push(user) } + .to change { organization.reload.updated_at } + .and change { member.reload.updated_at } + .and not_change { member_ticket.reload.updated_at } + end + end + + context 'with 100+ members' do + let!(:members) { create_list(:user, 101, organization: organization) } + let!(:member_ticket) { create(:ticket, customer: members.first) } + + # This _should_ be split into two separate examples, + # but setup is slow and expensive. + it 'does not perform any association updates' do + expect { organization.update(name: 'foo') } + .to not_change { members.map(&:reload).map(&:updated_at) } + .and not_change { member_ticket.reload.updated_at } + + expect { organization.members.push(member) } + .to not_change { organization.reload.updated_at } + .and not_change { members.map(&:reload).map(&:updated_at) } + end + end + end + end end diff --git a/test/unit/organization_ref_object_touch_test.rb b/test/unit/organization_ref_object_touch_test.rb deleted file mode 100644 index 6c5d43b1b..000000000 --- a/test/unit/organization_ref_object_touch_test.rb +++ /dev/null @@ -1,241 +0,0 @@ -require 'test_helper' - -class OrganizationRefObjectTouchTest < ActiveSupport::TestCase - - test 'check if ticket and customer has been updated' do - - # create base - groups = Group.where(name: 'Users') - roles = Role.where(name: 'Agent') - agent1 = User.create_or_update( - login: 'organization-ref-object-update-agent1@example.com', - firstname: 'Notification', - lastname: 'Agent1', - email: 'organization-ref-object-update-agent1@example.com', - password: 'agentpw', - active: true, - roles: roles, - groups: groups, - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - roles = Role.where(name: 'Customer') - organization1 = Organization.create_if_not_exists( - name: 'Ref Object Update Org 1', - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - organization2 = Organization.create_if_not_exists( - name: 'Ref Object Update Org 2', - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - customer1 = User.create_or_update( - login: 'organization-ref-object-update-customer1@example.com', - firstname: 'Notification', - lastname: 'Agent1', - email: 'organization-ref-object-update-customer1@example.com', - password: 'customerpw', - active: true, - organization_id: organization1.id, - roles: roles, - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - customer2 = User.create_or_update( - login: 'organization-ref-object-update-customer2@example.com', - firstname: 'Notification', - lastname: 'Agent2', - email: 'organization-ref-object-update-customer2@example.com', - password: 'customerpw', - active: true, - organization_id: organization2.id, - roles: roles, - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - - ticket = Ticket.create!( - title: "some title1\n äöüß", - group: Group.lookup(name: 'Users'), - customer_id: customer1.id, - owner_id: agent1.id, - state: Ticket::State.lookup(name: 'new'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_by_id: 1, - created_by_id: 1, - ) - assert(ticket, 'ticket created') - assert_equal(ticket.customer.id, customer1.id) - assert_equal(ticket.organization.id, organization1.id) - - travel 4.seconds - - organization1.name = 'Ref Object Update Org 1/1' - organization1.save! - - # check if ticket and customer has been touched - ticket = Ticket.find(ticket.id) - if ticket.updated_at > 2.seconds.ago - assert(true, 'ticket.updated_at has been updated') - else - assert(false, 'ticket.updated_at has not been updated') - end - - customer1.reload - if customer1.updated_at > 2.seconds.ago - assert(true, 'customer1.updated_at has been updated') - else - assert(false, 'customer1.updated_at has not been updated') - end - - travel 4.seconds - - customer2.organization_id = organization1.id - customer2.save! - - # check if customer1 and organization has been touched - customer1.reload - if customer1.updated_at > 2.seconds.ago - assert(true, 'customer1.updated_at has been updated') - else - assert(false, 'customer1.updated_at has not been updated') - end - - organization1.reload - if organization1.updated_at > 2.seconds.ago - assert(true, 'organization1.updated_at has been updated') - else - assert(false, 'organization1.updated_at has not been updated') - end - - assert(ticket.destroy, 'ticket destroy') - travel_back - end - - test 'check if ticket and customer has not been updated (different featrue propose)' do - - # create base - groups = Group.where(name: 'Users') - roles = Role.where(name: 'Agent') - agent1 = User.create_or_update( - login: 'organization-ref-object-not-update-agent1@example.com', - firstname: 'Notification', - lastname: 'Agent1', - email: 'organization-ref-object-not-update-agent1@example.com', - password: 'agentpw', - active: true, - roles: roles, - groups: groups, - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - roles = Role.where(name: 'Customer') - organization1 = Organization.create_if_not_exists( - name: 'Ref Object Update Org 1 (no update)', - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - organization2 = Organization.create_if_not_exists( - name: 'Ref Object Update Org 2 (no update)', - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - customer1 = User.create_or_update( - login: 'organization-ref-object-not-update-customer1@example.com', - firstname: 'Notification', - lastname: 'Agent1', - email: 'organization-ref-object-not-update-customer1@example.com', - password: 'customerpw', - active: true, - organization_id: organization1.id, - roles: roles, - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - customer2 = User.create_or_update( - login: 'organization-ref-object-not-update-customer2@example.com', - firstname: 'Notification', - lastname: 'Agent2', - email: 'organization-ref-object-not-update-customer2@example.com', - password: 'customerpw', - active: true, - organization_id: organization2.id, - roles: roles, - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - (1..100).each do |count| - User.create_or_update( - login: "organization-ref-object-update-customer3-#{count}@example.com", - firstname: 'Notification', - lastname: 'Agent2', - email: "organization-ref-object-update-customer3-#{count}@example.com", - password: 'customerpw', - active: true, - organization_id: organization1.id, - roles: roles, - updated_at: '2015-02-05 16:37:00', - updated_by_id: 1, - created_by_id: 1, - ) - end - - ticket = Ticket.create!( - title: "some title1\n äöüß", - group: Group.lookup(name: 'Users'), - customer_id: customer1.id, - owner_id: agent1.id, - state: Ticket::State.lookup(name: 'new'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_at: '2015-02-05 16:39:00', - updated_by_id: 1, - created_by_id: 1, - ) - assert(ticket, 'ticket created') - assert_equal(ticket.customer.id, customer1.id) - assert_equal(ticket.organization.id, organization1.id) - - customer1.reload - assert_not_equal('2015-02-05 16:37:00 UTC', customer1.updated_at.to_s) - customer1_updated_at = customer1.updated_at - - travel 4.seconds - organization1.name = 'Ref Object Update Org 1 (no update)/1' - organization1.save! - organization1_updated_at = organization1.updated_at - - # check if ticket and customer has been touched - ticket = Ticket.find(ticket.id) - assert_equal('2015-02-05 16:39:00 UTC', ticket.updated_at.to_s) - - customer1.reload - assert_equal(customer1_updated_at.to_s, customer1.updated_at.to_s) - - travel 4.seconds - - customer2.organization_id = organization1.id - customer2.save! - - # check if customer1 and organization has been touched - customer1.reload - assert_equal(customer1_updated_at.to_s, customer1.updated_at.to_s) - - organization1.reload - assert_equal(organization1_updated_at.to_s, organization1.updated_at.to_s) - - assert(ticket.destroy, 'ticket destroy') - travel_back - end - -end