From 3da068dcebb2dd13054474d363fc79be0963ec14 Mon Sep 17 00:00:00 2001
From: Tristan Read <tread@gitlab.com>
Date: Mon, 13 Feb 2023 19:47:09 +1300
Subject: [PATCH] Add search functionality to incident timeline resolver

Changelog: changed
---
 .../timeline_events_finder.rb                 |  3 +++
 .../timeline_events_resolver.rb               |  6 ++++++
 .../incident_management/timeline_event.rb     |  3 +++
 doc/api/graphql/reference/index.md            |  2 ++
 .../timeline_events_finder_spec.rb            | 18 +++++++++++++++++
 .../timeline_event_spec.rb                    | 20 +++++++++++++++++++
 6 files changed, 52 insertions(+)

diff --git a/app/finders/incident_management/timeline_events_finder.rb b/app/finders/incident_management/timeline_events_finder.rb
index aaf3133236aeff..0da40d8bf26057 100644
--- a/app/finders/incident_management/timeline_events_finder.rb
+++ b/app/finders/incident_management/timeline_events_finder.rb
@@ -12,6 +12,9 @@ def execute
       return ::IncidentManagement::TimelineEvent.none unless allowed?
 
       collection = incident.incident_management_timeline_events
+
+      collection = collection.with_tag_name(params[:tag_name]) if params[:tag_name]
+
       collection = by_id(collection)
       sort(collection)
     end
diff --git a/app/graphql/resolvers/incident_management/timeline_events_resolver.rb b/app/graphql/resolvers/incident_management/timeline_events_resolver.rb
index 0d46b1387b00f5..a362d5ee91d310 100644
--- a/app/graphql/resolvers/incident_management/timeline_events_resolver.rb
+++ b/app/graphql/resolvers/incident_management/timeline_events_resolver.rb
@@ -14,6 +14,12 @@ class TimelineEventsResolver < BaseResolver
                required: true,
                description: 'ID of the incident.'
 
+      argument :tag_name,
+               GraphQL::Types::String,
+               required: false,
+               description: 'Name of the tag to search on.',
+               default_value: nil
+
       when_single do
         argument :id,
                  ::Types::GlobalIDType[::IncidentManagement::TimelineEvent],
diff --git a/app/models/incident_management/timeline_event.rb b/app/models/incident_management/timeline_event.rb
index e70209f15389f9..eedb0b72d55445 100644
--- a/app/models/incident_management/timeline_event.rb
+++ b/app/models/incident_management/timeline_event.rb
@@ -29,5 +29,8 @@ class TimelineEvent < ApplicationRecord
       through: :timeline_event_tag_links
 
     scope :order_occurred_at_asc_id_asc, -> { reorder(occurred_at: :asc, id: :asc) }
+    scope :with_tag_name, ->(tag_name) do
+      joins(:timeline_event_tags).where(timeline_event_tags: { name: tag_name })
+    end
   end
 end
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 974da5560e4011..a434195be4a79c 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -20021,6 +20021,7 @@ Returns [`TimelineEventType`](#timelineeventtype).
 | ---- | ---- | ----------- |
 | <a id="projectincidentmanagementtimelineeventid"></a>`id` | [`IncidentManagementTimelineEventID!`](#incidentmanagementtimelineeventid) | ID of the timeline event. |
 | <a id="projectincidentmanagementtimelineeventincidentid"></a>`incidentId` | [`IssueID!`](#issueid) | ID of the incident. |
+| <a id="projectincidentmanagementtimelineeventtagname"></a>`tagName` | [`String`](#string) | Name of the tag to search on. |
 
 ##### `Project.incidentManagementTimelineEvents`
 
@@ -20037,6 +20038,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | Name | Type | Description |
 | ---- | ---- | ----------- |
 | <a id="projectincidentmanagementtimelineeventsincidentid"></a>`incidentId` | [`IssueID!`](#issueid) | ID of the incident. |
+| <a id="projectincidentmanagementtimelineeventstagname"></a>`tagName` | [`String`](#string) | Name of the tag to search on. |
 
 ##### `Project.issue`
 
diff --git a/spec/finders/incident_management/timeline_events_finder_spec.rb b/spec/finders/incident_management/timeline_events_finder_spec.rb
index aa01391c34388e..3386b9bfe9ccee 100644
--- a/spec/finders/incident_management/timeline_events_finder_spec.rb
+++ b/spec/finders/incident_management/timeline_events_finder_spec.rb
@@ -20,6 +20,16 @@
     create(:incident_management_timeline_event, project: project, incident: another_incident)
   end
 
+  let_it_be(:timeline_event_tag) do
+    create(:incident_management_timeline_event_tag, project: project, name: 'Start time')
+  end
+
+  let_it_be(:timeline_event_tag_link) do
+    create(:incident_management_timeline_event_tag_link,
+      timeline_event: timeline_event2,
+      timeline_event_tag: timeline_event_tag)
+  end
+
   let(:params) { {} }
 
   describe '#execute' do
@@ -42,6 +52,14 @@
         end
       end
 
+      context 'when filtering by Tag Name' do
+        let(:params) { { tag_name: "Start time" } }
+
+        it 'returns only matched timeline event' do
+          is_expected.to contain_exactly(timeline_event2)
+        end
+      end
+
       context 'when incident is nil' do
         let_it_be(:incident) { nil }
 
diff --git a/spec/models/incident_management/timeline_event_spec.rb b/spec/models/incident_management/timeline_event_spec.rb
index 036f5affb875bd..707d5a3d826d41 100644
--- a/spec/models/incident_management/timeline_event_spec.rb
+++ b/spec/models/incident_management/timeline_event_spec.rb
@@ -63,6 +63,26 @@
     end
   end
 
+  describe '.with_tag_name' do
+    let_it_be(:timeline_event_with_tag) do
+      create(:incident_management_timeline_event, project: project, incident: incident)
+    end
+
+    let_it_be(:timeline_event_tag) do
+      create(:incident_management_timeline_event_tag, project: project)
+    end
+
+    let_it_be(:timeline_event_tag_link) do
+      create(:incident_management_timeline_event_tag_link,
+        timeline_event: timeline_event_with_tag,
+        timeline_event_tag: timeline_event_tag)
+    end
+
+    it 'returns the correct event when filtering with a tag name' do
+      expect(described_class.with_tag_name('Start time')).to match_array([timeline_event_with_tag])
+    end
+  end
+
   describe '#cache_markdown_field' do
     let(:note) { 'note **bold** _italic_ `code` ![image](/path/img.png) :+1:👍' }
 
-- 
GitLab