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/award_emojis/add_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_schedule/create_spec.rb13
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_trigger/create_spec.rb75
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_trigger/delete_spec.rb63
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_trigger/update_spec.rb71
-rw-r--r--spec/requests/api/graphql/mutations/issues/update_spec.rb5
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_time_estimate_spec.rb41
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb44
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb26
-rw-r--r--spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb30
-rw-r--r--spec/requests/api/graphql/mutations/snippets/update_spec.rb10
-rw-r--r--spec/requests/api/graphql/mutations/work_items/create_spec.rb20
-rw-r--r--spec/requests/api/graphql/mutations/work_items/linked_items/add_spec.rb131
-rw-r--r--spec/requests/api/graphql/mutations/work_items/subscribe_spec.rb73
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_spec.rb4
16 files changed, 516 insertions, 94 deletions
diff --git a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
index 18cc85d36e0..dbace8f2b53 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe 'Adding an AwardEmoji', feature_category: :shared do
it_behaves_like 'a mutation that does not create an AwardEmoji'
it_behaves_like 'a mutation that returns top-level errors',
- errors: ['You cannot award emoji to this resource.']
+ errors: ['You cannot add emoji reactions to this resource.']
end
context 'when the given awardable is an Awardable' do
diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
index 7c6a487cdd0..65a5fb87f9a 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe 'Toggling an AwardEmoji', feature_category: :shared do
it_behaves_like 'a mutation that does not create or destroy an AwardEmoji'
it_behaves_like 'a mutation that returns top-level errors',
- errors: ['You cannot award emoji to this resource.']
+ errors: ['You cannot add emoji reactions to this resource.']
end
context 'when the given awardable is an Awardable' do
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_schedule/create_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_schedule/create_spec.rb
index 0d5e5f5d2fb..b2fe2754198 100644
--- a/spec/requests/api/graphql/mutations/ci/pipeline_schedule/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_schedule/create_spec.rb
@@ -68,8 +68,7 @@ RSpec.describe 'PipelineSchedulecreate', feature_category: :continuous_integrati
end
end
- # Move this from `shared_context` to `context` when `ci_refactoring_pipeline_schedule_create_service` is removed.
- shared_context 'when authorized' do # rubocop:disable RSpec/ContextWording
+ context 'when authorized' do
before_all do
project.add_developer(user)
end
@@ -149,14 +148,4 @@ RSpec.describe 'PipelineSchedulecreate', feature_category: :continuous_integrati
end
end
end
-
- it_behaves_like 'when authorized'
-
- context 'when the FF ci_refactoring_pipeline_schedule_create_service is disabled' do
- before do
- stub_feature_flags(ci_refactoring_pipeline_schedule_create_service: false)
- end
-
- it_behaves_like 'when authorized'
- end
end
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_trigger/create_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_trigger/create_spec.rb
new file mode 100644
index 00000000000..1af12d51e1e
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_trigger/create_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PipelineTriggerCreate', feature_category: :continuous_integration do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:project) { create(:project) }
+
+ let(:mutation) { graphql_mutation(:pipeline_trigger_create, params) }
+ let(:project_path) { project.full_path }
+ let(:description) { 'Ye old pipeline trigger token' }
+
+ let(:params) do
+ {
+ project_path: project_path,
+ description: description
+ }
+ end
+
+ subject { post_graphql_mutation(mutation, current_user: user) }
+
+ context 'when unauthorized' do
+ it 'returns an error' do
+ subject
+
+ expect(graphql_errors).not_to be_empty
+ expect(graphql_errors[0]['message'])
+ .to eq(
+ "The resource that you are attempting to access does not exist " \
+ "or you don't have permission to perform this action"
+ )
+ end
+ end
+
+ context 'when authorized' do
+ before_all do
+ project.add_owner(user)
+ end
+
+ context 'when the params are invalid' do
+ let(:description) { nil }
+
+ it 'does not create a pipeline trigger token and returns an error' do
+ expect { subject }.not_to change { project.triggers.count }
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_errors.to_s).to include('provided invalid value for description (Expected value to not be null)')
+ end
+ end
+
+ context 'when the params are valid' do
+ it 'creates a pipeline trigger token' do
+ expect { subject }.to change { project.triggers.count }.by(1)
+ expect(graphql_errors.to_s).to eql("")
+ end
+
+ it 'returns the new pipeline trigger token' do
+ subject
+
+ expect(graphql_data_at(:pipeline_trigger_create, :pipeline_trigger)).to match a_hash_including(
+ 'owner' => a_hash_including(
+ 'id' => user.to_global_id.to_s,
+ 'username' => user.username,
+ 'name' => user.name
+ ),
+ 'description' => description,
+ "canAccessProject" => true,
+ "hasTokenExposed" => true,
+ "lastUsed" => nil
+ )
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_trigger/delete_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_trigger/delete_spec.rb
new file mode 100644
index 00000000000..5ff2da30cb6
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_trigger/delete_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PipelineTriggerDelete', feature_category: :continuous_integration do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { build(:user) }
+ let_it_be(:project) { build(:project) }
+
+ let(:mutation) { graphql_mutation(:pipeline_trigger_delete, params) }
+
+ let_it_be(:trigger) { create(:ci_trigger, owner: current_user, project: project) }
+ let(:id) { trigger.to_global_id.to_s }
+
+ let(:params) do
+ {
+ id: id
+ }
+ end
+
+ subject { post_graphql_mutation(mutation, current_user: current_user) }
+
+ context 'when unauthorized' do
+ it_behaves_like 'a mutation on an unauthorized resource'
+ end
+
+ context 'when authorized' do
+ before_all do
+ project.add_owner(current_user)
+ end
+
+ context 'when the id is invalid' do
+ let(:id) { non_existing_record_id }
+
+ it_behaves_like 'an invalid argument to the mutation', argument_name: :id
+
+ it 'does not delete a pipeline trigger token' do
+ expect { subject }.not_to change { project.triggers.count }
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+
+ context 'when the id is nil' do
+ let(:id) { nil }
+
+ it_behaves_like 'an invalid argument to the mutation', argument_name: :id
+
+ it 'does not delete a pipeline trigger token' do
+ expect { subject }.not_to change { project.triggers.count }
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+
+ context 'when the params are valid' do
+ it_behaves_like 'a working GraphQL mutation'
+
+ it 'deletes the pipeline trigger token' do
+ expect { subject }.to change { project.triggers.count }.by(-1)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_trigger/update_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_trigger/update_spec.rb
new file mode 100644
index 00000000000..ce6e20c088e
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_trigger/update_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PipelineTriggerUpdate', feature_category: :continuous_integration do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { build(:user) }
+ let_it_be(:project) { build(:project) }
+
+ let(:mutation) { graphql_mutation(:pipeline_trigger_update, params) }
+ let_it_be(:old_description) { "Boring old description." }
+ let(:new_description) { 'Awesome new description!' }
+ let_it_be(:trigger) { create(:ci_trigger, owner: current_user, project: project, description: old_description) }
+
+ let(:params) do
+ {
+ id: trigger.to_global_id.to_s,
+ description: new_description
+ }
+ end
+
+ subject { post_graphql_mutation(mutation, current_user: current_user) }
+
+ context 'when unauthorized' do
+ it_behaves_like 'a mutation on an unauthorized resource'
+ end
+
+ context 'when authorized' do
+ before_all do
+ project.add_owner(current_user)
+ end
+
+ context 'when the params are invalid' do
+ let(:new_description) { nil }
+
+ it_behaves_like 'an invalid argument to the mutation', argument_name: 'description'
+
+ it 'does not update a pipeline trigger token' do
+ expect { subject }.not_to change { trigger }
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+
+ context 'when the params are valid' do
+ it_behaves_like 'a working GraphQL mutation'
+
+ it 'updates the pipeline trigger token' do
+ expect { subject }.to change { trigger.reload.description }.to(new_description)
+
+ expect(graphql_errors).to be_blank
+ end
+
+ it 'returns the updated trigger token' do
+ subject
+
+ expect(graphql_data_at(:pipeline_trigger_update, :pipeline_trigger)).to match a_hash_including(
+ 'owner' => a_hash_including(
+ 'id' => current_user.to_global_id.to_s,
+ 'username' => current_user.username,
+ 'name' => current_user.name
+ ),
+ 'description' => new_description,
+ "canAccessProject" => true,
+ "hasTokenExposed" => true,
+ "lastUsed" => nil
+ )
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/issues/update_spec.rb b/spec/requests/api/graphql/mutations/issues/update_spec.rb
index 97ead687a82..ff100d99628 100644
--- a/spec/requests/api/graphql/mutations/issues/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/update_spec.rb
@@ -147,5 +147,10 @@ RSpec.describe 'Update of an existing issue', feature_category: :team_planning d
end
end
end
+
+ it_behaves_like 'updating time estimate' do
+ let(:resource) { issue }
+ let(:mutation_name) { 'updateIssue' }
+ end
end
end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_time_estimate_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_time_estimate_spec.rb
new file mode 100644
index 00000000000..6bc130a97cf
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_time_estimate_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Setting time estimate of a merge request', feature_category: :code_review_workflow do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ let(:input) do
+ {
+ iid: merge_request.iid.to_s
+ }
+ end
+
+ let(:extra_params) { { project_path: project.full_path } }
+ let(:input_params) { input.merge(extra_params) }
+ let(:mutation) { graphql_mutation(:merge_request_update, input_params, nil, ['productAnalyticsState']) }
+ let(:mutation_response) { graphql_mutation_response(:merge_request_update) }
+
+ context 'when the user is not allowed to update a merge request' do
+ before_all do
+ project.add_reporter(current_user)
+ end
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when updating a time estimate' do
+ before_all do
+ project.add_developer(current_user)
+ end
+
+ it_behaves_like 'updating time estimate' do
+ let(:resource) { merge_request }
+ let(:mutation_name) { 'mergeRequestUpdate' }
+ end
+ end
+end
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 d81744abe1b..0e55b6f2c9f 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
@@ -43,9 +43,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_categ
project.add_reporter(current_user)
end
- it_behaves_like 'a mutation that returns top-level errors',
- errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
-
it 'does not create the annotation' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
@@ -58,25 +55,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_categ
project.add_developer(current_user)
end
- it 'creates the annotation' do
- expect do
- post_graphql_mutation(mutation, current_user: current_user)
- end.to change { Metrics::Dashboard::Annotation.count }.by(1)
- end
-
- it 'returns the created annotation' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- annotation = Metrics::Dashboard::Annotation.first
- annotation_id = GitlabSchema.id_from_object(annotation).to_s
-
- expect(mutation_response['annotation']['description']).to match(description)
- expect(mutation_response['annotation']['startingAt'].to_time).to match(starting_at.to_time)
- expect(mutation_response['annotation']['endingAt'].to_time).to match(ending_at.to_time)
- expect(mutation_response['annotation']['id']).to match(annotation_id)
- expect(annotation.environment_id).to eq(environment.id)
- end
-
context 'when environment_id is missing' do
let(:mutation) do
variables = {
@@ -137,25 +115,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_categ
project.add_developer(current_user)
end
- it 'creates the annotation' do
- expect do
- post_graphql_mutation(mutation, current_user: current_user)
- end.to change { Metrics::Dashboard::Annotation.count }.by(1)
- end
-
- it 'returns the created annotation' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- annotation = Metrics::Dashboard::Annotation.first
- annotation_id = GitlabSchema.id_from_object(annotation).to_s
-
- expect(mutation_response['annotation']['description']).to match(description)
- expect(mutation_response['annotation']['startingAt'].to_time).to match(starting_at.to_time)
- expect(mutation_response['annotation']['endingAt'].to_time).to match(ending_at.to_time)
- expect(mutation_response['annotation']['id']).to match(annotation_id)
- expect(annotation.cluster_id).to eq(cluster.id)
- end
-
context 'when cluster_id is missing' do
let(:mutation) do
variables = {
@@ -177,9 +136,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_categ
project.add_guest(current_user)
end
- it_behaves_like 'a mutation that returns top-level errors',
- errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
-
it 'does not create the annotation' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
index 09977cd19d7..c81f6381398 100644
--- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
@@ -7,8 +7,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete, feature_categ
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project, :private, :repository) }
- let_it_be(:environment) { create(:environment, project: project) }
- let_it_be(:annotation) { create(:metrics_dashboard_annotation, environment: environment) }
+ let_it_be(:annotation) { create(:metrics_dashboard_annotation) }
let(:variables) { { id: GitlabSchema.id_from_object(annotation).to_s } }
let(:mutation) { graphql_mutation(:delete_annotation, variables) }
@@ -28,14 +27,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete, feature_categ
project.add_developer(current_user)
end
- context 'with valid params' do
- it 'deletes the annotation' do
- expect do
- post_graphql_mutation(mutation, current_user: current_user)
- end.to change { Metrics::Dashboard::Annotation.count }.by(-1)
- end
- end
-
context 'with invalid params' do
let(:variables) { { id: GitlabSchema.id_from_object(project).to_s } }
@@ -44,21 +35,6 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete, feature_categ
end
end
- context 'when the delete fails' do
- let(:service_response) { { message: 'Annotation has not been deleted', status: :error, last_step: :delete } }
-
- before do
- allow_next_instance_of(Metrics::Dashboard::Annotations::DeleteService) do |delete_service|
- allow(delete_service).to receive(:execute).and_return(service_response)
- end
- end
- it 'returns the error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(mutation_response['errors']).to eq([service_response[:message]])
- end
- end
-
context 'when metrics dashboard feature is unavailable' do
before do
stub_feature_flags(remove_monitor_metrics: true)
diff --git a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
index 2f26a2f92b2..480e184a60c 100644
--- a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
@@ -15,6 +15,8 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis
maven_duplicate_exception_regex: 'foo-.*',
generic_duplicates_allowed: false,
generic_duplicate_exception_regex: 'bar-.*',
+ nuget_duplicates_allowed: false,
+ nuget_duplicate_exception_regex: 'bar-.*',
maven_package_requests_forwarding: true,
lock_maven_package_requests_forwarding: true,
npm_package_requests_forwarding: true,
@@ -32,6 +34,8 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis
mavenDuplicateExceptionRegex
genericDuplicatesAllowed
genericDuplicateExceptionRegex
+ nugetDuplicatesAllowed
+ nugetDuplicateExceptionRegex
mavenPackageRequestsForwarding
lockMavenPackageRequestsForwarding
npmPackageRequestsForwarding
@@ -58,6 +62,8 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis
expect(package_settings_response['mavenDuplicateExceptionRegex']).to eq(params[:maven_duplicate_exception_regex])
expect(package_settings_response['genericDuplicatesAllowed']).to eq(params[:generic_duplicates_allowed])
expect(package_settings_response['genericDuplicateExceptionRegex']).to eq(params[:generic_duplicate_exception_regex])
+ expect(package_settings_response['nugetDuplicatesAllowed']).to eq(params[:nuget_duplicates_allowed])
+ expect(package_settings_response['nugetDuplicateExceptionRegex']).to eq(params[:nuget_duplicate_exception_regex])
expect(package_settings_response['mavenPackageRequestsForwarding']).to eq(params[:maven_package_requests_forwarding])
expect(package_settings_response['lockMavenPackageRequestsForwarding']).to eq(params[:lock_maven_package_requests_forwarding])
expect(package_settings_response['pypiPackageRequestsForwarding']).to eq(params[:pypi_package_requests_forwarding])
@@ -98,6 +104,8 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis
maven_duplicate_exception_regex: 'SNAPSHOT',
generic_duplicates_allowed: true,
generic_duplicate_exception_regex: 'foo',
+ nuget_duplicates_allowed: true,
+ nuget_duplicate_exception_regex: 'foo',
maven_package_requests_forwarding: nil,
lock_maven_package_requests_forwarding: false,
npm_package_requests_forwarding: nil,
@@ -109,6 +117,8 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis
maven_duplicate_exception_regex: 'foo-.*',
generic_duplicates_allowed: false,
generic_duplicate_exception_regex: 'bar-.*',
+ nuget_duplicates_allowed: false,
+ nuget_duplicate_exception_regex: 'bar-.*',
maven_package_requests_forwarding: true,
lock_maven_package_requests_forwarding: true,
npm_package_requests_forwarding: true,
@@ -119,6 +129,26 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis
it_behaves_like 'returning a success'
it_behaves_like 'rejecting invalid regex'
+
+ context 'when nuget_duplicates_option FF is disabled' do
+ let(:params) do
+ {
+ namespace_path: namespace.full_path,
+ 'nugetDuplicatesAllowed' => false
+ }
+ end
+
+ before do
+ stub_feature_flags(nuget_duplicates_option: false)
+ end
+
+ it 'raises an error', :aggregate_failures do
+ subject
+
+ expect(graphql_errors.size).to eq(1)
+ expect(graphql_errors.first['message']).to include('feature flag is disabled')
+ end
+ end
end
RSpec.shared_examples 'accepting the mutation request creating the package settings' do
diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
index 7c5ab691b51..06594d89338 100644
--- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
@@ -188,16 +188,10 @@ RSpec.describe 'Updating a Snippet', feature_category: :source_code_management d
stub_session('warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt])
end
- it_behaves_like 'Snowplow event tracking with RedisHLL context' do
+ it_behaves_like 'internal event tracking' do
+ let(:action) { ::Gitlab::UsageDataCounters::EditorUniqueCounter::EDIT_BY_SNIPPET_EDITOR }
let(:user) { current_user }
- let(:property) { 'g_edit_by_snippet_ide' }
let(:namespace) { project.namespace }
- let(:category) { 'Gitlab::UsageDataCounters::EditorUniqueCounter' }
- let(:action) { 'ide_edit' }
- let(:label) { 'usage_activity_by_stage_monthly.create.action_monthly_active_users_ide_edit' }
- let(:context) do
- [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event_name).to_context]
- end
end
end
end
diff --git a/spec/requests/api/graphql/mutations/work_items/create_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_spec.rb
index fca3c84e534..78b93c3210b 100644
--- a/spec/requests/api/graphql/mutations/work_items/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/create_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe 'Create a work item', feature_category: :team_planning do
}
end
- before(:all) do
+ before_all do
create(:parent_link, work_item_parent: parent, work_item: adjacent, relative_position: 0)
end
@@ -264,6 +264,14 @@ RSpec.describe 'Create a work item', feature_category: :team_planning do
let(:mutation) { graphql_mutation(:workItemCreate, input.merge('namespacePath' => project.full_path), fields) }
it_behaves_like 'creates work item'
+
+ context 'when the namespace_level_work_items feature flag is disabled' do
+ before do
+ stub_feature_flags(namespace_level_work_items: false)
+ end
+
+ it_behaves_like 'creates work item'
+ end
end
end
@@ -272,6 +280,16 @@ RSpec.describe 'Create a work item', feature_category: :team_planning do
let(:mutation) { graphql_mutation(:workItemCreate, input.merge(namespacePath: group.full_path), fields) }
it_behaves_like 'creates work item'
+
+ context 'when the namespace_level_work_items feature flag is disabled' do
+ before do
+ stub_feature_flags(namespace_level_work_items: false)
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors', errors: [
+ Mutations::WorkItems::Create::DISABLED_FF_ERROR
+ ]
+ end
end
context 'when both projectPath and namespacePath are passed' do
diff --git a/spec/requests/api/graphql/mutations/work_items/linked_items/add_spec.rb b/spec/requests/api/graphql/mutations/work_items/linked_items/add_spec.rb
new file mode 100644
index 00000000000..f18e0e44905
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/work_items/linked_items/add_spec.rb
@@ -0,0 +1,131 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Add linked items to a work item", feature_category: :portfolio_management do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:reporter) { create(:user).tap { |user| project.add_reporter(user) } }
+ let_it_be(:work_item) { create(:work_item, project: project) }
+ let_it_be(:related1) { create(:work_item, project: project) }
+ let_it_be(:related2) { create(:work_item, project: project) }
+
+ let(:mutation_response) { graphql_mutation_response(:work_item_add_linked_items) }
+ let(:mutation) { graphql_mutation(:workItemAddLinkedItems, input, fields) }
+
+ let(:ids_to_link) { [related1.to_global_id.to_s, related2.to_global_id.to_s] }
+ let(:input) { { 'id' => work_item.to_global_id.to_s, 'workItemsIds' => ids_to_link } }
+
+ let(:fields) do
+ <<~FIELDS
+ workItem {
+ id
+ widgets {
+ type
+ ... on WorkItemWidgetLinkedItems {
+ linkedItems {
+ edges {
+ node {
+ linkType
+ workItem {
+ id
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ errors
+ message
+ FIELDS
+ end
+
+ context 'when the user is not allowed to read the 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 read the work item' do
+ let(:current_user) { reporter }
+
+ it 'links the work items' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change { WorkItems::RelatedWorkItemLink.count }.by(2)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']).to include('id' => work_item.to_global_id.to_s)
+ expect(mutation_response['message']).to eq("Successfully linked ID(s): #{related1.id} and #{related2.id}.")
+ expect(mutation_response['workItem']['widgets']).to include(
+ {
+ 'linkedItems' => { 'edges' => match_array([
+ { 'node' => { 'linkType' => 'relates_to', 'workItem' => { 'id' => related1.to_global_id.to_s } } },
+ { 'node' => { 'linkType' => 'relates_to', 'workItem' => { 'id' => related2.to_global_id.to_s } } }
+ ]) },
+ 'type' => 'LINKED_ITEMS'
+ }
+ )
+ end
+
+ context 'when linking a work item fails' do
+ let_it_be(:private_project) { create(:project, :private) }
+ let_it_be(:related2) { create(:work_item, project: private_project) }
+
+ it 'adds valid items and returns an error message for failed item' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change { WorkItems::RelatedWorkItemLink.count }.by(1)
+
+ expect(mutation_response['errors']).to contain_exactly(
+ "Item with ID: #{related2.id} cannot be added. " \
+ "You don't have permission to perform this action."
+ )
+ end
+
+ context 'when a work item does not exist' do
+ let(:input) do
+ {
+ 'id' => work_item.to_global_id.to_s,
+ 'workItemsIds' => ["gid://gitlab/WorkItem/#{non_existing_record_id}"]
+ }
+ end
+
+ it 'returns an error message' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.not_to change { WorkItems::RelatedWorkItemLink.count }
+
+ expect_graphql_errors_to_include("Couldn't find WorkItem with 'id'=#{non_existing_record_id}")
+ end
+ end
+
+ context 'when there are more than the max allowed items to link' do
+ let(:max_work_items) { Mutations::WorkItems::LinkedItems::Base::MAX_WORK_ITEMS }
+ let(:error_msg) { "No more than #{max_work_items} work items can be linked at the same time." }
+
+ before do
+ max_work_items.times { |i| ids_to_link.push("gid://gitlab/WorkItem/#{i}") }
+ end
+
+ it 'returns an error message' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.not_to change { WorkItems::RelatedWorkItemLink.count }
+
+ expect_graphql_errors_to_include("No more than #{max_work_items} work items can be linked at the same time.")
+ end
+ end
+ end
+
+ context 'when `linked_work_items` feature flag is disabled' do
+ before do
+ stub_feature_flags(linked_work_items: false)
+ end
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/work_items/subscribe_spec.rb b/spec/requests/api/graphql/mutations/work_items/subscribe_spec.rb
new file mode 100644
index 00000000000..00672332082
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/work_items/subscribe_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Subscribe to a work item', feature_category: :team_planning do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:guest) { create(:user).tap { |user| project.add_guest(user) } }
+ let_it_be(:work_item) { create(:work_item, project: project) }
+
+ let(:subscribed_state) { true }
+ let(:mutation_input) { { 'id' => work_item.to_global_id.to_s, 'subscribed' => subscribed_state } }
+ let(:mutation) { graphql_mutation(:workItemSubscribe, mutation_input, fields) }
+ let(:mutation_response) { graphql_mutation_response(:work_item_subscribe) }
+ let(:fields) do
+ <<~FIELDS
+ workItem {
+ widgets {
+ type
+ ... on WorkItemWidgetNotifications {
+ subscribed
+ }
+ }
+ }
+ errors
+ FIELDS
+ end
+
+ context 'when user is not allowed to update subscription work items' do
+ let(:current_user) { create(:user) }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context
+
+ context 'when user has permissions to update its subscription to the work items' do
+ let(:current_user) { guest }
+
+ it "subscribe the user to the work item's notifications" do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change { work_item.subscribed?(current_user, project) }.to(true)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']['widgets']).to include({
+ 'type' => 'NOTIFICATIONS',
+ 'subscribed' => true
+ })
+ end
+
+ context 'when unsunscribing' do
+ let(:subscribed_state) { false }
+
+ before do
+ create(:subscription, project: project, user: current_user, subscribable: work_item, subscribed: true)
+ end
+
+ it "unsubscribe the user from the work item's notifications" do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change { work_item.subscribed?(current_user, project) }.to(false)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']['widgets']).to include({
+ 'type' => 'NOTIFICATIONS',
+ 'subscribed' => false
+ })
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
index ea9516f256c..cff21c10a5a 100644
--- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
@@ -573,7 +573,7 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do
end
context 'when updating relative position' do
- before(:all) do
+ before_all do
create(:parent_link, work_item_parent: valid_parent, work_item: valid_child1)
create(:parent_link, work_item_parent: valid_parent, work_item: valid_child2)
end
@@ -655,7 +655,7 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do
let_it_be(:work_item, reload: true) { create(:work_item, :task, project: project) }
context "when parent is already assigned" do
- before(:all) do
+ before_all do
create(:parent_link, work_item_parent: valid_parent, work_item: work_item)
create(:parent_link, work_item_parent: valid_parent, work_item: valid_child1)
create(:parent_link, work_item_parent: valid_parent, work_item: valid_child2)