From 966309f7852c23bbcfa9a61b04fa4cfc66cc2472 Mon Sep 17 00:00:00 2001 From: Mario Celi <mcelicalderon@gitlab.com> Date: Tue, 2 Aug 2022 12:07:48 -0500 Subject: [PATCH] Add `issuableDatesUpdated` subscription to GraphQL API Changelog: added Updating start or due date in an Issue or WorkItem will now trigger a relatime update so you can fetch the updated dates --- app/graphql/graphql_triggers.rb | 4 ++ app/graphql/types/subscription_type.rb | 3 ++ app/services/issues/update_service.rb | 7 +++ spec/graphql/graphql_triggers_spec.rb | 14 ++++++ spec/graphql/types/subscription_type_spec.rb | 1 + spec/services/issues/update_service_spec.rb | 46 +++++++++++++++++++ .../work_items/update_service_spec.rb | 34 ++++++++++++++ 7 files changed, 109 insertions(+) diff --git a/app/graphql/graphql_triggers.rb b/app/graphql/graphql_triggers.rb index 342cff83e907d..b39875b83a99e 100644 --- a/app/graphql/graphql_triggers.rb +++ b/app/graphql/graphql_triggers.rb @@ -16,4 +16,8 @@ def self.issuable_title_updated(issuable) def self.issuable_labels_updated(issuable) GitlabSchema.subscriptions.trigger('issuableLabelsUpdated', { issuable_id: issuable.to_gid }, issuable) end + + def self.issuable_dates_updated(issuable) + GitlabSchema.subscriptions.trigger('issuableDatesUpdated', { issuable_id: issuable.to_gid }, issuable) + end end diff --git a/app/graphql/types/subscription_type.rb b/app/graphql/types/subscription_type.rb index 18d6d51a30cd8..9b5f028a8570a 100644 --- a/app/graphql/types/subscription_type.rb +++ b/app/graphql/types/subscription_type.rb @@ -15,5 +15,8 @@ class SubscriptionType < ::Types::BaseObject field :issuable_labels_updated, subscription: Subscriptions::IssuableUpdated, null: true, description: 'Triggered when the labels of an issuable are updated.' + + field :issuable_dates_updated, subscription: Subscriptions::IssuableUpdated, null: true, + description: 'Triggered when the due date or start date of an issuable is updated.' end end diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index afc61eed2872e..46c28d82ddc49 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -70,6 +70,7 @@ def handle_changes(issue, options) handle_severity_change(issue, old_severity) handle_escalation_status_change(issue) handle_issue_type_change(issue) + handle_date_changes(issue) end def handle_assignee_changes(issue, old_assignees) @@ -116,6 +117,12 @@ def move_issue_to_new_project(issue) attr_reader :spam_params + def handle_date_changes(issue) + return unless issue.previous_changes.slice('due_date', 'start_date').any? + + GraphqlTriggers.issuable_dates_updated(issue) + end + def clone_issue(issue) target_project = params.delete(:target_clone_project) with_notes = params.delete(:clone_with_notes) diff --git a/spec/graphql/graphql_triggers_spec.rb b/spec/graphql/graphql_triggers_spec.rb index 84af33a5cb3f0..5e2ab74a0e5c6 100644 --- a/spec/graphql/graphql_triggers_spec.rb +++ b/spec/graphql/graphql_triggers_spec.rb @@ -47,4 +47,18 @@ GraphqlTriggers.issuable_labels_updated(issue) end end + + describe '.issuable_dates_updated' do + it 'triggers the issuableDatesUpdated subscription' do + work_item = create(:work_item) + + expect(GitlabSchema.subscriptions).to receive(:trigger).with( + 'issuableDatesUpdated', + { issuable_id: work_item.to_gid }, + work_item + ).and_call_original + + GraphqlTriggers.issuable_dates_updated(work_item) + end + end end diff --git a/spec/graphql/types/subscription_type_spec.rb b/spec/graphql/types/subscription_type_spec.rb index 1a2629ed422a1..9b043fa52cf0c 100644 --- a/spec/graphql/types/subscription_type_spec.rb +++ b/spec/graphql/types/subscription_type_spec.rb @@ -9,6 +9,7 @@ issue_crm_contacts_updated issuable_title_updated issuable_labels_updated + issuable_dates_updated ] expect(described_class).to have_graphql_fields(*expected_fields).only diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index e2e8828ae89d1..9ef969d802b44 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -988,6 +988,52 @@ def update_issue(opts) end end + context 'updating dates' do + subject(:result) { described_class.new(project: project, current_user: user, params: params).execute(issue) } + + let(:updated_date) { 1.week.from_now.to_date } + + shared_examples 'issue update service that triggers date updates' do + it 'triggers graphql date updated subscription' do + expect(GraphqlTriggers).to receive(:issuable_dates_updated).with(issue).and_call_original + + result + end + end + + shared_examples 'issue update service that does not trigger date updates' do + it 'does not trigger date updated subscriptions' do + expect(GraphqlTriggers).not_to receive(:issuable_dates_updated) + + result + end + end + + context 'when due_date is updated' do + let(:params) { { due_date: updated_date } } + + it_behaves_like 'issue update service that triggers date updates' + end + + context 'when start_date is updated' do + let(:params) { { start_date: updated_date } } + + it_behaves_like 'issue update service that triggers date updates' + end + + context 'when no date is updated' do + let(:params) { { title: 'should not trigger date updates' } } + + it_behaves_like 'issue update service that does not trigger date updates' + end + + context 'when update is not successful but date is provided' do + let(:params) { { title: '', due_date: updated_date } } + + it_behaves_like 'issue update service that does not trigger date updates' + end + end + context 'updating asssignee_id' do it 'does not update assignee when assignee_id is invalid' do update_issue(assignee_ids: [-1]) diff --git a/spec/services/work_items/update_service_spec.rb b/spec/services/work_items/update_service_spec.rb index dd5924e743459..7715fad970337 100644 --- a/spec/services/work_items/update_service_spec.rb +++ b/spec/services/work_items/update_service_spec.rb @@ -36,6 +36,14 @@ stub_spam_services end + shared_examples 'update service that triggers graphql dates updated subscription' do + it 'triggers graphql subscription issueableDatesUpdated' do + expect(GraphqlTriggers).to receive(:issuable_dates_updated).with(work_item).and_call_original + + update_work_item + end + end + context 'when title is changed' do let(:opts) { { title: 'changed' } } @@ -187,6 +195,32 @@ end end + context 'for start and due date widget' do + let(:updated_date) { 1.week.from_now.to_date } + + context 'when due_date is updated' do + let(:widget_params) { { start_and_due_date_widget: { due_date: updated_date } } } + + it_behaves_like 'update service that triggers graphql dates updated subscription' + end + + context 'when start_date is updated' do + let(:widget_params) { { start_and_due_date_widget: { start_date: updated_date } } } + + it_behaves_like 'update service that triggers graphql dates updated subscription' + end + + context 'when no date param is updated' do + let(:opts) { { title: 'should not trigger' } } + + it 'does not trigger date updated subscription' do + expect(GraphqlTriggers).not_to receive(:issuable_dates_updated) + + update_work_item + end + end + end + context 'for the hierarchy widget' do let(:opts) { { title: 'changed' } } let_it_be(:child_work_item) { create(:work_item, :task, project: project) } -- GitLab