Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/api/graphql/mutations')
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb17
-rw-r--r--spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/design_management/delete_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb12
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb8
-rw-r--r--spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/jira_import/start_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb10
-rw-r--r--spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb109
-rw-r--r--spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb103
-rw-r--r--spec/requests/api/graphql/mutations/releases/create_spec.rb20
-rw-r--r--spec/requests/api/graphql/mutations/user_preferences/update_spec.rb22
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_task_spec.rb101
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb78
18 files changed, 435 insertions, 61 deletions
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
index 37656ab4eea..7abd5ca8772 100644
--- a/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
@@ -28,4 +28,21 @@ RSpec.describe 'PipelineDestroy' do
expect(response).to have_gitlab_http_status(:success)
expect { pipeline.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
+
+ context 'when project is undergoing stats refresh' do
+ before do
+ create(:project_build_artifacts_size_refresh, :pending, project: pipeline.project)
+ end
+
+ it 'returns an error and does not destroy the pipeline' do
+ expect(Gitlab::ProjectStatsRefreshConflictsLogger)
+ .to receive(:warn_request_rejected_during_stats_refresh)
+ .with(pipeline.project.id)
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(graphql_mutation_response(:pipeline_destroy)['errors']).not_to be_empty
+ expect(pipeline.reload).to be_persisted
+ end
+ end
end
diff --git a/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb b/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb
index decb2e7bccc..ef00f45ef18 100644
--- a/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb
+++ b/spec/requests/api/graphql/mutations/container_repository/destroy_tags_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe 'Destroying a container repository tags' do
it 'returns too many tags error' do
expect { subject }.not_to change { ::Packages::Event.count }
- explanation = graphql_errors.dig(0, 'extensions', 'problems', 0, 'explanation')
+ explanation = graphql_errors.dig(0, 'message')
expect(explanation).to eq(Mutations::ContainerRepositories::DestroyTags::TOO_MANY_TAGS_ERROR_MESSAGE)
end
end
diff --git a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
index 1f43f113e65..e2ab08b301b 100644
--- a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe "deleting designs" do
context 'the designs list is empty' do
it_behaves_like 'a failed request' do
let(:designs) { [] }
- let(:the_error) { a_string_matching %r/was provided invalid value/ }
+ let(:the_error) { a_string_matching %r/no filenames/ }
end
end
diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb
index 3ea8b38e20f..923e12a3c06 100644
--- a/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event/create_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe 'Creating an incident timeline event' do
},
'note' => note,
'action' => 'comment',
- 'editable' => false,
+ 'editable' => true,
'occurredAt' => event_occurred_at.iso8601
)
end
diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb
index faff3bfe23a..85208869ad9 100644
--- a/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event/destroy_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe 'Removing an incident timeline event' do
},
'note' => timeline_event.note,
'noteHtml' => timeline_event.note_html,
- 'editable' => false,
+ 'editable' => true,
'action' => timeline_event.action,
'occurredAt' => timeline_event.occurred_at.iso8601,
'createdAt' => timeline_event.created_at.iso8601,
diff --git a/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb b/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb
index b92f6af1d3d..9272e218172 100644
--- a/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe 'Promote an incident timeline event from a comment' do
},
'note' => comment.note,
'action' => 'comment',
- 'editable' => false,
+ 'editable' => true,
'occurredAt' => comment.created_at.iso8601
)
end
diff --git a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
index 715507c3cc5..395a490bfc3 100644
--- a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
@@ -102,18 +102,6 @@ RSpec.describe 'Setting issues crm contacts' do
group.add_reporter(user)
end
- context 'when the feature is disabled' do
- before do
- stub_feature_flags(customer_relations: false)
- end
-
- it 'raises expected error' do
- post_graphql_mutation(mutation, current_user: user)
-
- expect(graphql_errors).to include(a_hash_including('message' => 'Feature disabled'))
- end
- end
-
it_behaves_like 'successful mutation'
context 'when the contact does not exist' do
diff --git a/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb b/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb
index 0166871502b..a81364d37b2 100644
--- a/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb
@@ -49,14 +49,6 @@ RSpec.describe 'Setting the escalation status of an incident' do
it_behaves_like 'a mutation that returns top-level errors', errors: ['Feature unavailable for provided issue']
end
- context 'with feature disabled' do
- before do
- stub_feature_flags(incident_escalations: false)
- end
-
- it_behaves_like 'a mutation that returns top-level errors', errors: ['Feature unavailable for provided issue']
- end
-
it 'sets given escalation_policy to the escalation status for the issue' do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb b/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb
index 45cc70f09fd..b438e1ba881 100644
--- a/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb
+++ b/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Importing Jira Users' do
- include JiraServiceHelper
+ include JiraIntegrationHelpers
include GraphqlHelpers
let_it_be(:user) { create(:user) }
diff --git a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
index b14305281af..1508ba31e37 100644
--- a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
+++ b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Starting a Jira Import' do
- include JiraServiceHelper
+ include JiraIntegrationHelpers
include GraphqlHelpers
let_it_be(:user) { create(:user) }
diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
index 5bc3c68cf26..9ef443af76a 100644
--- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
@@ -76,7 +76,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create do
context 'when environment_id is missing' do
let(:mutation) do
variables = {
- environment_id: nil,
starting_at: starting_at,
ending_at: ending_at,
dashboard_path: dashboard_path,
@@ -147,7 +146,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create do
context 'when cluster_id is missing' do
let(:mutation) do
variables = {
- cluster_id: nil,
starting_at: starting_at,
ending_at: ending_at,
dashboard_path: dashboard_path,
diff --git a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb
index 0f7ccac3179..c4674155aa0 100644
--- a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb
@@ -68,15 +68,7 @@ RSpec.describe 'Repositioning an ImageDiffNote' do
let(:new_position) { { x: nil } }
it_behaves_like 'a mutation that returns top-level errors' do
- let(:match_errors) { include(/RepositionImageDiffNoteInput! was provided invalid value/) }
- end
-
- it 'contains an explanation for the error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- explanation = graphql_errors.first['extensions']['problems'].first['explanation']
-
- expect(explanation).to eq('At least one property of `UpdateDiffImagePositionInput` must be set')
+ let(:match_errors) { include(/At least one property of `UpdateDiffImagePositionInput` must be set/) }
end
end
end
diff --git a/spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb b/spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb
new file mode 100644
index 00000000000..7e00f3ca53a
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/packages/cleanup/policy/update_spec.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Updating the packages cleanup policy' do
+ include GraphqlHelpers
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:project, reload: true) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ let(:params) do
+ {
+ project_path: project.full_path,
+ keep_n_duplicated_package_files: 'TWENTY_PACKAGE_FILES'
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(:update_packages_cleanup_policy, params,
+ <<~QUERY
+ packagesCleanupPolicy {
+ keepNDuplicatedPackageFiles
+ nextRunAt
+ }
+ errors
+ QUERY
+ )
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:update_packages_cleanup_policy) }
+ let(:packages_cleanup_policy_response) { mutation_response['packagesCleanupPolicy'] }
+
+ shared_examples 'accepting the mutation request and updates the existing policy' do
+ it 'returns the updated packages cleanup policy' do
+ expect { subject }.not_to change { ::Packages::Cleanup::Policy.count }
+
+ expect(project.packages_cleanup_policy.keep_n_duplicated_package_files).to eq('20')
+ expect_graphql_errors_to_be_empty
+ expect(packages_cleanup_policy_response['keepNDuplicatedPackageFiles'])
+ .to eq(params[:keep_n_duplicated_package_files])
+ expect(packages_cleanup_policy_response['nextRunAt']).not_to eq(nil)
+ end
+ end
+
+ shared_examples 'accepting the mutation request and creates a policy' do
+ it 'returns the created packages cleanup policy' do
+ expect { subject }.to change { ::Packages::Cleanup::Policy.count }.by(1)
+
+ expect(project.packages_cleanup_policy.keep_n_duplicated_package_files).to eq('20')
+ expect_graphql_errors_to_be_empty
+ expect(packages_cleanup_policy_response['keepNDuplicatedPackageFiles'])
+ .to eq(params[:keep_n_duplicated_package_files])
+ expect(packages_cleanup_policy_response['nextRunAt']).not_to eq(nil)
+ end
+ end
+
+ shared_examples 'denying the mutation request' do
+ it 'returns an error' do
+ expect { subject }.not_to change { ::Packages::Cleanup::Policy.count }
+
+ expect(project.packages_cleanup_policy.keep_n_duplicated_package_files).not_to eq('20')
+ expect(mutation_response).to be_nil
+ expect_graphql_errors_to_include(/you don't have permission to perform this action/)
+ end
+ end
+
+ describe 'post graphql mutation' do
+ subject { post_graphql_mutation(mutation, current_user: user) }
+
+ context 'with existing packages cleanup policy' do
+ let_it_be(:project_packages_cleanup_policy) { create(:packages_cleanup_policy, project: project) }
+
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'accepting the mutation request and updates the existing policy'
+ :developer | 'denying the mutation request'
+ :reporter | 'denying the mutation request'
+ :guest | 'denying the mutation request'
+ :anonymous | 'denying the mutation request'
+ end
+
+ with_them do
+ before do
+ project.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+
+ context 'without existing packages cleanup policy' do
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'accepting the mutation request and creates a policy'
+ :developer | 'denying the mutation request'
+ :reporter | 'denying the mutation request'
+ :guest | 'denying the mutation request'
+ :anonymous | 'denying the mutation request'
+ end
+
+ with_them do
+ before do
+ project.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb b/spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb
new file mode 100644
index 00000000000..002cd634ebd
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/packages/destroy_files_spec.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Destroying multiple package files' do
+ using RSpec::Parameterized::TableSyntax
+
+ include GraphqlHelpers
+
+ let_it_be_with_reload(:package) { create(:maven_package) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { package.project }
+
+ let(:ids) { package.package_files.first(2).map { |pf| pf.to_global_id.to_s } }
+
+ let(:query) do
+ <<~GQL
+ errors
+ GQL
+ end
+
+ let(:params) do
+ {
+ project_path: project.full_path,
+ ids: ids
+ }
+ end
+
+ let(:mutation) { graphql_mutation(:destroy_package_files, params, query) }
+
+ describe 'post graphql mutation' do
+ subject(:mutation_request) { post_graphql_mutation(mutation, current_user: user) }
+
+ shared_examples 'destroying the package files' do
+ it 'marks the package file as pending destruction' do
+ expect { mutation_request }.to change { ::Packages::PackageFile.pending_destruction.count }.by(2)
+ end
+
+ it_behaves_like 'returning response status', :success
+ end
+
+ shared_examples 'denying the mutation request' do |response = "you don't have permission to perform this action"|
+ it 'does not mark the package file as pending destruction' do
+ expect { mutation_request }.not_to change { ::Packages::PackageFile.pending_destruction.count }
+
+ expect_graphql_errors_to_include(response)
+ end
+
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'with valid params' do
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'destroying the package files'
+ :developer | 'denying the mutation request'
+ :reporter | 'denying the mutation request'
+ :guest | 'denying the mutation request'
+ :anonymous | 'denying the mutation request'
+ end
+
+ with_them do
+ before do
+ project.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ it_behaves_like params[:shared_examples_name]
+ end
+
+ context 'with more than 100 files' do
+ let(:ids) { package.package_files.map { |pf| pf.to_global_id.to_s } }
+
+ before do
+ project.add_maintainer(user)
+ create_list(:package_file, 99, package: package)
+ end
+
+ it_behaves_like 'denying the mutation request', 'Cannot delete more than 100 files'
+ end
+
+ context 'with files outside of the project' do
+ let_it_be(:package2) { create(:maven_package) }
+
+ let(:ids) { super().push(package2.package_files.first.to_global_id.to_s) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it_behaves_like 'denying the mutation request', 'All files must be in the requested project'
+ end
+ end
+
+ context 'with invalid params' do
+ let(:params) { { id: 'foo' } }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it_behaves_like 'denying the mutation request', 'invalid value for id'
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb
index 86995c10f10..1e62942c29d 100644
--- a/spec/requests/api/graphql/mutations/releases/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe 'Creation of a new release' do
let(:mutation_name) { :release_create }
let(:tag_name) { 'v7.12.5'}
+ let(:tag_message) { nil }
let(:ref) { 'master'}
let(:name) { 'Version 7.12.5'}
let(:description) { 'Release 7.12.5 :rocket:' }
@@ -29,6 +30,7 @@ RSpec.describe 'Creation of a new release' do
{
projectPath: project.full_path,
tagName: tag_name,
+ tagMessage: tag_message,
ref: ref,
name: name,
description: description,
@@ -191,10 +193,26 @@ RSpec.describe 'Creation of a new release' do
context 'when the provided tag does not already exist' do
let(:tag_name) { 'v7.12.5-alpha' }
+ after do
+ project.repository.rm_tag(developer, tag_name)
+ end
+
it_behaves_like 'no errors'
- it 'creates a new tag' do
+ it 'creates a new lightweight tag' do
expect { create_release }.to change { Project.find_by_id(project.id).repository.tag_count }.by(1)
+ expect(project.repository.find_tag(tag_name).message).to be_blank
+ end
+
+ context 'and tag_message is provided' do
+ let(:tag_message) { 'Annotated tag message' }
+
+ it_behaves_like 'no errors'
+
+ it 'creates a new annotated tag with the message' do
+ expect { create_release }.to change { Project.find_by_id(project.id).repository.tag_count }.by(1)
+ expect(project.repository.find_tag(tag_name).message).to eq(tag_message)
+ end
end
end
diff --git a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
index 85194e6eb20..e1c7fd9d60d 100644
--- a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb
@@ -28,17 +28,6 @@ RSpec.describe Mutations::UserPreferences::Update do
expect(current_user.user_preference.persisted?).to eq(true)
expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s)
end
-
- context 'when incident_escalations feature flag is disabled' do
- let(:sort_value) { 'ESCALATION_STATUS_ASC' }
-
- before do
- stub_feature_flags(incident_escalations: false)
- end
-
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['Feature flag `incident_escalations` must be enabled to use this sort order.']
- end
end
context 'when user has existing preference' do
@@ -56,16 +45,5 @@ RSpec.describe Mutations::UserPreferences::Update do
expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s)
end
-
- context 'when incident_escalations feature flag is disabled' do
- let(:sort_value) { 'ESCALATION_STATUS_DESC' }
-
- before do
- stub_feature_flags(incident_escalations: false)
- end
-
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['Feature flag `incident_escalations` must be enabled to use this sort order.']
- end
end
end
diff --git a/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb
new file mode 100644
index 00000000000..32468a46ace
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Update a work item task' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
+ let_it_be(:unauthorized_work_item) { create(:work_item) }
+ let_it_be(:referenced_work_item, refind: true) { create(:work_item, project: project, title: 'REFERENCED') }
+ let_it_be(:parent_work_item) do
+ create(:work_item, project: project, description: "- [ ] #{referenced_work_item.to_reference}+")
+ end
+
+ let(:task) { referenced_work_item }
+ let(:work_item) { parent_work_item }
+ let(:task_params) { { 'title' => 'UPDATED' } }
+ let(:task_input) { { 'id' => task.to_global_id.to_s }.merge(task_params) }
+ let(:input) { { 'id' => work_item.to_global_id.to_s, 'taskData' => task_input } }
+ let(:mutation) { graphql_mutation(:workItemUpdateTask, input) }
+ let(:mutation_response) { graphql_mutation_response(:work_item_update_task) }
+
+ context 'the user is not allowed to read a work item' do
+ let(:current_user) { create(:user) }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to update a work item' do
+ let(:current_user) { developer }
+
+ it 'updates the work item and invalidates markdown cache on the original work item' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ referenced_work_item.reload
+ end.to change(referenced_work_item, :title).from(referenced_work_item.title).to('UPDATED')
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response).to include(
+ 'workItem' => hash_including(
+ 'title' => work_item.title,
+ 'descriptionHtml' => a_string_including('UPDATED')
+ ),
+ 'task' => hash_including(
+ 'title' => 'UPDATED'
+ )
+ )
+ end
+
+ context 'when providing invalid task params' do
+ let(:task_params) { { 'title' => '' } }
+
+ it 'makes no changes to the DB and returns an error message' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ task.reload
+ end.to not_change(task, :title).and(
+ not_change(work_item, :description_html)
+ )
+
+ expect(mutation_response['errors']).to contain_exactly("Title can't be blank")
+ end
+ end
+
+ context 'when user cannot update the task' do
+ let(:task) { unauthorized_work_item }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::WorkItems::UpdateTask }
+ end
+
+ context 'when the work_items feature flag is disabled' do
+ before do
+ stub_feature_flags(work_items: false)
+ end
+
+ it 'does not update the task item and returns and error' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ task.reload
+ end.to not_change(task, :title)
+
+ expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
+ end
+ end
+ end
+
+ context 'when user does not have permissions to update a work item' do
+ let(:current_user) { developer }
+ let(:work_item) { unauthorized_work_item }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb
new file mode 100644
index 00000000000..595d8fe97ed
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Update work item widgets' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
+ let_it_be(:work_item, refind: true) { create(:work_item, project: project) }
+
+ let(:input) do
+ {
+ 'descriptionWidget' => { 'description' => 'updated description' }
+ }
+ end
+
+ let(:mutation) { graphql_mutation(:workItemUpdateWidgets, input.merge('id' => work_item.to_global_id.to_s)) }
+
+ let(:mutation_response) { graphql_mutation_response(:work_item_update_widgets) }
+
+ context 'the user is not allowed to update a work item' do
+ let(:current_user) { create(:user) }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to update a work item', :aggregate_failures do
+ let(:current_user) { developer }
+
+ context 'when the updated work item is not valid' do
+ it 'returns validation errors without the work item' do
+ errors = ActiveModel::Errors.new(work_item).tap { |e| e.add(:description, 'error message') }
+
+ allow_next_found_instance_of(::WorkItem) do |instance|
+ allow(instance).to receive(:valid?).and_return(false)
+ allow(instance).to receive(:errors).and_return(errors)
+ end
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(mutation_response['workItem']).to be_nil
+ expect(mutation_response['errors']).to match_array(['Description error message'])
+ end
+ end
+
+ it 'updates the work item widgets' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :description).from(nil).to('updated description')
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']).to include(
+ 'title' => work_item.title
+ )
+ end
+
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::WorkItems::UpdateWidgets }
+ end
+
+ context 'when the work_items feature flag is disabled' do
+ before do
+ stub_feature_flags(work_items: false)
+ end
+
+ it 'does not update the work item and returns and error' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to not_change(work_item, :title)
+
+ expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
+ end
+ end
+ end
+end