From e55071ecfb409e1b7561c0b68f33b6eb90c0d317 Mon Sep 17 00:00:00 2001 From: Kassio Borges <kborges@gitlab.com> Date: Wed, 19 Jun 2024 15:07:05 +0000 Subject: [PATCH] Add missing ResourceLinkEvent#synthetic_note_class Related to: - https://gitlab.com/gitlab-org/gitlab/-/issues/467243 - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114394 - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/107584 Changelog: fixed --- .../concerns/work_item_resource_event.rb | 13 +++- app/models/resource_event.rb | 2 +- app/models/work_items/resource_link_event.rb | 4 ++ spec/models/resource_event_spec.rb | 63 ++++++++++++++++--- .../models/resource_event_shared_examples.rb | 7 +++ 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/app/models/concerns/work_item_resource_event.rb b/app/models/concerns/work_item_resource_event.rb index ddf39787f63b8..d3f8419a77eea 100644 --- a/app/models/concerns/work_item_resource_event.rb +++ b/app/models/concerns/work_item_resource_event.rb @@ -20,8 +20,10 @@ def trigger_note_subscription_create(events: self) end def work_item_synthetic_system_note(events: nil) - # System notes for label resource events are handled in batches, so that we have single system note for multiple - # label changes. + return unless synthetic_note_class + + # System notes for label resource events are handled in batches, + # so that we have single system note for multiple label changes. if is_a?(ResourceLabelEvent) && events.present? return synthetic_note_class.from_events(events, resource: work_item, resource_parent: work_item.project) end @@ -29,7 +31,12 @@ def work_item_synthetic_system_note(events: nil) synthetic_note_class.from_event(self, resource: work_item, resource_parent: work_item.project) end + # Class used to create the even synthetic note + # If the event does not require a synthetic note the method must return false def synthetic_note_class - raise NoMethodError, 'must implement `synthetic_note_class` method' + raise NoMethodError, <<~MESSAGE.squish + `#{self.class.name}#synthetic_note_class` method must be implemented + (return nil if event does not require a note) + MESSAGE end end diff --git a/app/models/resource_event.rb b/app/models/resource_event.rb index 551ea98413295..88c1576a41bf4 100644 --- a/app/models/resource_event.rb +++ b/app/models/resource_event.rb @@ -21,7 +21,7 @@ def discussion_id end def issuable - raise NoMethodError, 'must implement `issuable` method' + raise NoMethodError, "`#{self.class.name}#issuable` method must be implemented" end private diff --git a/app/models/work_items/resource_link_event.rb b/app/models/work_items/resource_link_event.rb index 6725acf8c68c9..b0f52b447e50d 100644 --- a/app/models/work_items/resource_link_event.rb +++ b/app/models/work_items/resource_link_event.rb @@ -10,6 +10,10 @@ class ResourceLinkEvent < ResourceEvent add: 1, remove: 2 } + + def synthetic_note_class + nil + end end end diff --git a/spec/models/resource_event_spec.rb b/spec/models/resource_event_spec.rb index 62bd5314b6932..e141c2e4632ff 100644 --- a/spec/models/resource_event_spec.rb +++ b/spec/models/resource_event_spec.rb @@ -3,17 +3,62 @@ require 'spec_helper' RSpec.describe ResourceEvent, feature_category: :team_planning, type: :model do - let(:dummy_resource_label_event_class) do - Class.new(ResourceEvent) do - self.table_name = 'resource_label_events' + context 'when inheriting from ResourceEvent' do + context 'when it does not implement the #issuable method' do + let(:dummy_resource_label_event_class) do + Class.new(ResourceEvent) do + self.table_name = 'resource_label_events' + + def self.name + 'DummyResourceLabelEventClass' + end + end + end + + it 'raises error on not implemented `issuable` method' do + expect { dummy_resource_label_event_class.new.issuable } + .to raise_error( + NoMethodError, + "`DummyResourceLabelEventClass#issuable` method must be implemented" + ) + end end - end - it 'raises error on not implemented `issuable` method' do - expect { dummy_resource_label_event_class.new.issuable }.to raise_error(NoMethodError) - end + context 'when it does not implement the #synthetic_note_class method' do + let(:dummy_resource_label_event_class) do + Class.new(ResourceEvent) do + self.table_name = 'resource_label_events' + + def self.name + 'DummyResourceLabelEventClass' + end + + def issuable + :issuable + end + end + end - it 'raises error on not implemented `synthetic_note_class` method' do - expect { dummy_resource_label_event_class.new.synthetic_note_class }.to raise_error(NoMethodError) + it 'raises error on not implemented `issuable` method' do + expect { dummy_resource_label_event_class.new.synthetic_note_class } + .to raise_error(NoMethodError, <<~MESSAGE.squish) + `DummyResourceLabelEventClass#synthetic_note_class` method must be implemented + (return nil if event does not require a note) + MESSAGE + end + end + + it 'must implement #synthetic_note_class method', :aggregate_failures do + Dir['{ee/,}app/models/**/resource*event.rb'].each do |klass| + require(Rails.root.join(klass)) + end + + described_class.subclasses.each do |klass| + next if klass.abstract_class? + + expect { klass.new.synthetic_note_class } + .not_to(raise_error) + end + end end end diff --git a/spec/support/shared_examples/models/resource_event_shared_examples.rb b/spec/support/shared_examples/models/resource_event_shared_examples.rb index 853d6635305ea..b3cd7281a3070 100644 --- a/spec/support/shared_examples/models/resource_event_shared_examples.rb +++ b/spec/support/shared_examples/models/resource_event_shared_examples.rb @@ -53,6 +53,13 @@ expect(events).to be_empty end end + + describe '#synthetic_note_class' do + it 'must implement #synthetic_note_class method' do + expect { described_class.new.synthetic_note_class } + .not_to raise_error + end + end end RSpec.shared_examples 'a resource event that responds to imported' do -- GitLab