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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 11:27:35 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 11:27:35 +0300
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /spec/graphql/mutations
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'spec/graphql/mutations')
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/create_spec.rb57
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/http_integration/update_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb72
-rw-r--r--spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb58
-rw-r--r--spec/graphql/mutations/alert_management/update_alert_status_spec.rb4
-rw-r--r--spec/graphql/mutations/commits/create_spec.rb29
-rw-r--r--spec/graphql/mutations/container_expiration_policies/update_spec.rb20
-rw-r--r--spec/graphql/mutations/container_repositories/destroy_spec.rb67
-rw-r--r--spec/graphql/mutations/issues/set_assignees_spec.rb14
-rw-r--r--spec/graphql/mutations/issues/set_confidential_spec.rb4
-rw-r--r--spec/graphql/mutations/issues/set_due_date_spec.rb4
-rw-r--r--spec/graphql/mutations/issues/set_locked_spec.rb4
-rw-r--r--spec/graphql/mutations/issues/set_severity_spec.rb6
-rw-r--r--spec/graphql/mutations/issues/update_spec.rb6
-rw-r--r--spec/graphql/mutations/labels/create_spec.rb80
-rw-r--r--spec/graphql/mutations/merge_requests/set_assignees_spec.rb14
-rw-r--r--spec/graphql/mutations/merge_requests/set_labels_spec.rb4
-rw-r--r--spec/graphql/mutations/merge_requests/set_locked_spec.rb4
-rw-r--r--spec/graphql/mutations/merge_requests/set_milestone_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_wip_spec.rb4
-rw-r--r--spec/graphql/mutations/merge_requests/update_spec.rb4
-rw-r--r--spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb60
-rw-r--r--spec/graphql/mutations/releases/create_spec.rb133
-rw-r--r--spec/graphql/mutations/terraform/state/delete_spec.rb55
-rw-r--r--spec/graphql/mutations/terraform/state/lock_spec.rb68
-rw-r--r--spec/graphql/mutations/terraform/state/unlock_spec.rb61
-rw-r--r--spec/graphql/mutations/todos/create_spec.rb44
-rw-r--r--spec/graphql/mutations/todos/mark_all_done_spec.rb2
-rw-r--r--spec/graphql/mutations/todos/restore_many_spec.rb19
32 files changed, 1086 insertions, 45 deletions
diff --git a/spec/graphql/mutations/alert_management/http_integration/create_spec.rb b/spec/graphql/mutations/alert_management/http_integration/create_spec.rb
new file mode 100644
index 00000000000..9aa89761aaf
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/create_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::Create do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:args) { { project_path: project.full_path, active: true, name: 'HTTP Integration' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::CreateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: ::AlertManagement::HttpIntegration.last!,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::CreateService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::CreateService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'An integration already exists'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['An integration already exists']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb b/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb
new file mode 100644
index 00000000000..f74f9186743
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::Destroy do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration) } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::DestroyService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::DestroyService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::DestroyService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'An error has occurred'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['An error has occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb b/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb
new file mode 100644
index 00000000000..d3ffb2abb47
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::ResetToken do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration) } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::UpdateService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'Token cannot be reset'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['Token cannot be reset']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/http_integration/update_spec.rb b/spec/graphql/mutations/alert_management/http_integration/update_spec.rb
new file mode 100644
index 00000000000..d6318e3161d
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/http_integration/update_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::HttpIntegration::Update do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration), active: false, name: 'New Name' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when HttpIntegrations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::AlertManagement::HttpIntegrations::UpdateService)
+ .to receive(:execute)
+ .and_return(ServiceResponse.error(payload: { integration: nil }, message: 'Failed to update'))
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['Failed to update']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb b/spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
new file mode 100644
index 00000000000..02a5e2e74e2
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::PrometheusIntegration::Create do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:args) { { project_path: project.full_path, active: true, api_url: 'http://prometheus.com/' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when Prometheus Integration already exists' do
+ let_it_be(:existing_integration) { create(:prometheus_service, project: project) }
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['Multiple Prometheus integrations are not supported']
+ )
+ end
+ end
+
+ context 'when UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: ::PrometheusService.last!,
+ errors: []
+ )
+ end
+
+ it 'creates a corresponding token' do
+ expect { resolve }.to change(::Alerting::ProjectAlertingSetting, :count).by(1)
+ end
+ end
+
+ context 'when UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::Projects::Operations::UpdateService)
+ .to receive(:execute)
+ .and_return({ status: :error, message: 'An error occurred' })
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: nil,
+ errors: ['An error occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb b/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb
new file mode 100644
index 00000000000..45d92695e06
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::PrometheusIntegration::ResetToken do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:prometheus_service, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration) } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::Projects::Operations::UpdateService)
+ .to receive(:execute)
+ .and_return({ status: :error, message: 'An error occurred' })
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: ['An error occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb b/spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb
new file mode 100644
index 00000000000..eab4474d827
--- /dev/null
+++ b/spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::AlertManagement::PrometheusIntegration::Update do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:integration) { create(:prometheus_service, project: project) }
+ let(:args) { { id: GitlabSchema.id_from_object(integration), active: false, api_url: 'http://new-url.com' } }
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
+
+ describe '#resolve' do
+ subject(:resolve) { mutation_for(project, current_user).resolve(args) }
+
+ context 'user has sufficient access to project' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with success' do
+ it 'returns the integration with no errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: []
+ )
+ end
+ end
+
+ context 'when ::Projects::Operations::UpdateService responds with an error' do
+ before do
+ allow_any_instance_of(::Projects::Operations::UpdateService)
+ .to receive(:execute)
+ .and_return({ status: :error, message: 'An error occurred' })
+ end
+
+ it 'returns errors' do
+ expect(resolve).to eq(
+ integration: integration,
+ errors: ['An error occurred']
+ )
+ end
+ end
+ end
+
+ context 'when resource is not accessible to the user' do
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+
+ private
+
+ def mutation_for(project, user)
+ described_class.new(object: project, context: { current_user: user }, field: nil)
+ end
+end
diff --git a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
index ab98088ebcd..08761ce64c2 100644
--- a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
+++ b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
@@ -37,8 +37,8 @@ RSpec.describe Mutations::AlertManagement::UpdateAlertStatus do
context 'error occurs when updating' do
it 'returns the alert with errors' do
# Stub an error on the alert
- allow_next_instance_of(Resolvers::AlertManagement::AlertResolver) do |resolver|
- allow(resolver).to receive(:resolve).and_return(alert)
+ allow_next_instance_of(::AlertManagement::AlertsFinder) do |finder|
+ allow(finder).to receive(:execute).and_return([alert])
end
allow(alert).to receive(:save).and_return(false)
diff --git a/spec/graphql/mutations/commits/create_spec.rb b/spec/graphql/mutations/commits/create_spec.rb
index fb1baafe7bd..82a5e3a62f5 100644
--- a/spec/graphql/mutations/commits/create_spec.rb
+++ b/spec/graphql/mutations/commits/create_spec.rb
@@ -5,8 +5,9 @@ require 'spec_helper'
RSpec.describe Mutations::Commits::Create do
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
- let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+
let(:context) do
GraphQL::Query::Context.new(
query: OpenStruct.new(schema: nil),
@@ -18,9 +19,10 @@ RSpec.describe Mutations::Commits::Create do
specify { expect(described_class).to require_graphql_authorizations(:push_code) }
describe '#resolve' do
- subject { mutation.resolve(project_path: project.full_path, branch: branch, message: message, actions: actions) }
+ subject { mutation.resolve(project_path: project.full_path, branch: branch, start_branch: start_branch, message: message, actions: actions) }
let(:branch) { 'master' }
+ let(:start_branch) { nil }
let(:message) { 'Commit message' }
let(:actions) do
[
@@ -142,6 +144,29 @@ RSpec.describe Mutations::Commits::Create do
end
end
+ context 'when branch does not exist and a start branch is provided' do
+ let(:branch) { 'my-branch' }
+ let(:start_branch) { 'master' }
+ let(:actions) do
+ [
+ {
+ action: 'create',
+ file_path: 'ANOTHER_FILE.md',
+ content: 'Bye'
+ }
+ ]
+ end
+
+ it 'returns a new commit' do
+ expect(mutated_commit).to have_attributes(message: message, project: project)
+ expect(subject[:errors]).to be_empty
+
+ expect_to_contain_deltas([
+ a_hash_including(a_mode: '0', b_mode: '100644', new_file: true, new_path: 'ANOTHER_FILE.md')
+ ])
+ end
+ end
+
context 'when message is not set' do
let(:message) { nil }
diff --git a/spec/graphql/mutations/container_expiration_policies/update_spec.rb b/spec/graphql/mutations/container_expiration_policies/update_spec.rb
index 6aedaab3b53..9c6016e0af4 100644
--- a/spec/graphql/mutations/container_expiration_policies/update_spec.rb
+++ b/spec/graphql/mutations/container_expiration_policies/update_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe Mutations::ContainerExpirationPolicies::Update do
it_behaves_like 'not creating the container expiration policy'
- it "doesn't update the cadence" do
+ it 'doesn\'t update the cadence' do
expect { subject }
.not_to change { container_expiration_policy.reload.cadence }
end
@@ -47,6 +47,24 @@ RSpec.describe Mutations::ContainerExpirationPolicies::Update do
)
end
end
+
+ context 'with blank regex' do
+ let_it_be(:params) { { project_path: project.full_path, name_regex: '', enabled: true } }
+
+ it_behaves_like 'not creating the container expiration policy'
+
+ it "doesn't update the cadence" do
+ expect { subject }
+ .not_to change { container_expiration_policy.reload.cadence }
+ end
+
+ it 'returns an error' do
+ expect(subject).to eq(
+ container_expiration_policy: nil,
+ errors: ['Name regex can\'t be blank']
+ )
+ end
+ end
end
RSpec.shared_examples 'denying access to container expiration policy' do
diff --git a/spec/graphql/mutations/container_repositories/destroy_spec.rb b/spec/graphql/mutations/container_repositories/destroy_spec.rb
new file mode 100644
index 00000000000..3903196a511
--- /dev/null
+++ b/spec/graphql/mutations/container_repositories/destroy_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::ContainerRepositories::Destroy do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be_with_reload(:container_repository) { create(:container_repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:project) { container_repository.project }
+ let(:id) { container_repository.to_global_id.to_s }
+
+ specify { expect(described_class).to require_graphql_authorizations(:destroy_container_image) }
+
+ describe '#resolve' do
+ subject do
+ described_class.new(object: nil, context: { current_user: user }, field: nil)
+ .resolve(id: id)
+ end
+
+ shared_examples 'destroying the container repository' do
+ it 'destroys the container repistory' do
+ expect(::Packages::CreateEventService)
+ .to receive(:new).with(nil, user, event_name: :delete_repository, scope: :container).and_call_original
+ expect(DeleteContainerRepositoryWorker)
+ .to receive(:perform_async).with(user.id, container_repository.id)
+
+ expect { subject }.to change { ::Packages::Event.count }.by(1)
+ expect(container_repository.reload.delete_scheduled?).to be true
+ end
+ end
+
+ shared_examples 'denying access to container respository' do
+ it 'raises an error' do
+ expect(DeleteContainerRepositoryWorker)
+ .not_to receive(:perform_async).with(user.id, container_repository.id)
+
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'with valid id' do
+ where(:user_role, :shared_examples_name) do
+ :maintainer | 'destroying the container repository'
+ :developer | 'destroying the container repository'
+ :reporter | 'denying access to container respository'
+ :guest | 'denying access to container respository'
+ :anonymous | 'denying access to container respository'
+ 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 'with invalid id' do
+ let(:id) { 'gid://gitlab/ContainerRepository/5555' }
+
+ it_behaves_like 'denying access to container respository'
+ end
+ end
+end
diff --git a/spec/graphql/mutations/issues/set_assignees_spec.rb b/spec/graphql/mutations/issues/set_assignees_spec.rb
index 77ba511b715..9a27c5acdac 100644
--- a/spec/graphql/mutations/issues/set_assignees_spec.rb
+++ b/spec/graphql/mutations/issues/set_assignees_spec.rb
@@ -3,6 +3,20 @@
require 'spec_helper'
RSpec.describe Mutations::Issues::SetAssignees do
+ context 'when the user does not have permissions' do
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+
+ subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+
+ describe '#resolve' do
+ subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, assignee_usernames: [assignee.username]) }
+
+ it_behaves_like 'permission level for issue mutation is correctly verified'
+ end
+ end
+
it_behaves_like 'an assignable resource' do
let_it_be(:resource, reload: true) { create(:issue) }
end
diff --git a/spec/graphql/mutations/issues/set_confidential_spec.rb b/spec/graphql/mutations/issues/set_confidential_spec.rb
index 0b2fc0ecb93..c3269e5c0c0 100644
--- a/spec/graphql/mutations/issues/set_confidential_spec.rb
+++ b/spec/graphql/mutations/issues/set_confidential_spec.rb
@@ -17,9 +17,7 @@ RSpec.describe Mutations::Issues::SetConfidential do
subject { mutation.resolve(project_path: project.full_path, iid: issue.iid, confidential: confidential) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/issues/set_due_date_spec.rb b/spec/graphql/mutations/issues/set_due_date_spec.rb
index a638971d966..9f8d0d6c405 100644
--- a/spec/graphql/mutations/issues/set_due_date_spec.rb
+++ b/spec/graphql/mutations/issues/set_due_date_spec.rb
@@ -16,9 +16,7 @@ RSpec.describe Mutations::Issues::SetDueDate do
subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, due_date: due_date) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/issues/set_locked_spec.rb b/spec/graphql/mutations/issues/set_locked_spec.rb
index 10438226c17..1a0af0c6c63 100644
--- a/spec/graphql/mutations/issues/set_locked_spec.rb
+++ b/spec/graphql/mutations/issues/set_locked_spec.rb
@@ -15,9 +15,7 @@ RSpec.describe Mutations::Issues::SetLocked do
subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, locked: locked) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
let(:mutated_issue) { subject[:issue] }
diff --git a/spec/graphql/mutations/issues/set_severity_spec.rb b/spec/graphql/mutations/issues/set_severity_spec.rb
index ed73d3b777e..7698118ae3e 100644
--- a/spec/graphql/mutations/issues/set_severity_spec.rb
+++ b/spec/graphql/mutations/issues/set_severity_spec.rb
@@ -15,11 +15,7 @@ RSpec.describe Mutations::Issues::SetSeverity do
subject(:resolve) { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, severity: severity) }
- context 'when the user cannot update the issue' do
- it 'raises an error' do
- expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/issues/update_spec.rb b/spec/graphql/mutations/issues/update_spec.rb
index f9f4bdeb6fa..ce1eb874bcf 100644
--- a/spec/graphql/mutations/issues/update_spec.rb
+++ b/spec/graphql/mutations/issues/update_spec.rb
@@ -35,11 +35,7 @@ RSpec.describe Mutations::Issues::Update do
subject { mutation.resolve(mutation_params) }
- context 'when the user cannot access the issue' do
- it 'raises an error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
- end
+ it_behaves_like 'permission level for issue mutation is correctly verified'
context 'when the user can update the issue' do
before do
diff --git a/spec/graphql/mutations/labels/create_spec.rb b/spec/graphql/mutations/labels/create_spec.rb
new file mode 100644
index 00000000000..8b284816d63
--- /dev/null
+++ b/spec/graphql/mutations/labels/create_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Labels::Create do
+ let_it_be(:user) { create(:user) }
+
+ let(:attributes) do
+ {
+ title: 'new title',
+ description: 'A new label'
+ }
+ end
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+ let(:mutated_label) { subject[:label] }
+
+ shared_examples 'create labels mutation' do
+ describe '#resolve' do
+ subject { mutation.resolve(attributes.merge(extra_params)) }
+
+ context 'when the user does not have permission to create a label' do
+ before do
+ parent.add_guest(user)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when the user can create a label' do
+ before do
+ parent.add_developer(user)
+ end
+
+ it 'creates label with correct values' do
+ expect(mutated_label).to have_attributes(attributes)
+ end
+ end
+ end
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_label) }
+
+ context 'when creating a project label' do
+ let_it_be(:parent) { create(:project) }
+ let(:extra_params) { { project_path: parent.full_path } }
+
+ it_behaves_like 'create labels mutation'
+ end
+
+ context 'when creating a group label' do
+ let_it_be(:parent) { create(:group) }
+ let(:extra_params) { { group_path: parent.full_path } }
+
+ it_behaves_like 'create labels mutation'
+ end
+
+ describe '#ready?' do
+ subject { mutation.ready?(attributes.merge(extra_params)) }
+
+ context 'when passing both project_path and group_path' do
+ let(:extra_params) { { project_path: 'foo', group_path: 'bar' } }
+
+ it 'raises an argument error' do
+ expect { subject }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Exactly one of/)
+ end
+ end
+
+ context 'when passing only project_path or group_path' do
+ let(:extra_params) { { project_path: 'foo' } }
+
+ it 'does not raise an error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
index 4ac40fc09c6..e2eab591341 100644
--- a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
@@ -3,6 +3,20 @@
require 'spec_helper'
RSpec.describe Mutations::MergeRequests::SetAssignees do
+ context 'when the user does not have permissions' do
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+
+ subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+
+ describe '#resolve' do
+ subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, assignee_usernames: [assignee.username]) }
+
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
+ end
+ end
+
it_behaves_like 'an assignable resource' do
let_it_be(:resource, reload: true) { create(:merge_request) }
end
diff --git a/spec/graphql/mutations/merge_requests/set_labels_spec.rb b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
index 62a7f650f84..1bb303cf99b 100644
--- a/spec/graphql/mutations/merge_requests/set_labels_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
@@ -18,9 +18,7 @@ RSpec.describe Mutations::MergeRequests::SetLabels do
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, label_ids: label_ids) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/merge_requests/set_locked_spec.rb b/spec/graphql/mutations/merge_requests/set_locked_spec.rb
index aca7df5445f..03c709e9bb3 100644
--- a/spec/graphql/mutations/merge_requests/set_locked_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_locked_spec.rb
@@ -16,9 +16,7 @@ RSpec.describe Mutations::MergeRequests::SetLocked do
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, locked: locked) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/merge_requests/set_milestone_spec.rb b/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
index ccb2d9bd132..4de857f43e3 100644
--- a/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
@@ -18,6 +18,8 @@ RSpec.describe Mutations::MergeRequests::SetMilestone do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
+
context 'when the user can update the merge request' do
before do
project.add_developer(user)
diff --git a/spec/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/graphql/mutations/merge_requests/set_wip_spec.rb
index b6cb49724fa..69f6a4328b8 100644
--- a/spec/graphql/mutations/merge_requests/set_wip_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_wip_spec.rb
@@ -16,9 +16,7 @@ RSpec.describe Mutations::MergeRequests::SetWip do
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, wip: wip) }
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/merge_requests/update_spec.rb b/spec/graphql/mutations/merge_requests/update_spec.rb
index 4a1fdf6e74b..8acd2562ea8 100644
--- a/spec/graphql/mutations/merge_requests/update_spec.rb
+++ b/spec/graphql/mutations/merge_requests/update_spec.rb
@@ -18,9 +18,7 @@ RSpec.describe Mutations::MergeRequests::Update do
mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, **attributes)
end
- it 'raises an error if the resource is not accessible to the user' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
context 'when the user can update the merge request' do
before do
diff --git a/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
new file mode 100644
index 00000000000..8c22e1a1cb6
--- /dev/null
+++ b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Notes::RepositionImageDiffNote do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ subject do
+ mutation.resolve({ note: note, position: new_position })
+ end
+
+ let_it_be(:noteable) { create(:merge_request) }
+ let_it_be(:project) { noteable.project }
+ let(:note) { create(:image_diff_note_on_merge_request, noteable: noteable, project: project) }
+
+ let(:mutation) do
+ described_class.new(object: nil, context: { current_user: user }, field: nil)
+ end
+
+ let(:new_position) do
+ { x: 10, y: 11, width: 12, height: 13 }
+ end
+
+ context 'when the user does not have permission' do
+ let(:user) { nil }
+
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(
+ Gitlab::Graphql::Errors::ResourceNotAvailable,
+ "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 the user has permission' do
+ let(:user) { project.creator }
+ let(:mutated_note) { subject[:note] }
+ let(:errors) { subject[:errors] }
+
+ it 'mutates the note', :aggregate_failures do
+ expect { subject }.to change { note.reset.position.to_h }.to(include(new_position))
+
+ expect(mutated_note).to eq(note)
+ expect(errors).to be_empty
+ end
+
+ context 'when the note is a DiffNote, but not on an image' do
+ let(:note) { create(:diff_note_on_merge_request, noteable: noteable, project: project) }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(
+ Gitlab::Graphql::Errors::ResourceNotAvailable,
+ 'Resource is not an ImageDiffNote'
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/releases/create_spec.rb b/spec/graphql/mutations/releases/create_spec.rb
new file mode 100644
index 00000000000..d6305691dac
--- /dev/null
+++ b/spec/graphql/mutations/releases/create_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Releases::Create do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:milestone_12_3) { create(:milestone, project: project, title: '12.3') }
+ let_it_be(:milestone_12_4) { create(:milestone, project: project, title: '12.4') }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+
+ let(:tag) { 'v1.1.0'}
+ let(:ref) { 'master'}
+ let(:name) { 'Version 1.0'}
+ let(:description) { 'The first release :rocket:' }
+ let(:released_at) { Time.parse('2018-12-10') }
+ let(:milestones) { [milestone_12_3.title, milestone_12_4.title] }
+ let(:assets) do
+ {
+ links: [
+ {
+ name: 'An asset link',
+ url: 'https://gitlab.example.com/link',
+ filepath: '/permanent/link',
+ link_type: 'other'
+ }
+ ]
+ }
+ end
+
+ let(:mutation_arguments) do
+ {
+ project_path: project.full_path,
+ tag: tag,
+ ref: ref,
+ name: name,
+ description: description,
+ released_at: released_at,
+ milestones: milestones,
+ assets: assets
+ }
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ before do
+ project.add_reporter(reporter)
+ project.add_developer(developer)
+ end
+
+ describe '#resolve' do
+ subject(:resolve) do
+ mutation.resolve(**mutation_arguments)
+ end
+
+ let(:new_release) { subject[:release] }
+
+ context 'when the current user has access to create releases' do
+ let(:current_user) { developer }
+
+ it 'returns no errors' do
+ expect(resolve).to include(errors: [])
+ end
+
+ it 'creates the release with the correct tag' do
+ expect(new_release.tag).to eq(tag)
+ end
+
+ it 'creates the release with the correct name' do
+ expect(new_release.name).to eq(name)
+ end
+
+ it 'creates the release with the correct description' do
+ expect(new_release.description).to eq(description)
+ end
+
+ it 'creates the release with the correct released_at' do
+ expect(new_release.released_at).to eq(released_at)
+ end
+
+ it 'creates the release with the correct created_at' do
+ expect(new_release.created_at).to eq(Time.current)
+ end
+
+ it 'creates the release with the correct milestone associations' do
+ expected_milestone_titles = [milestone_12_3.title, milestone_12_4.title]
+ actual_milestone_titles = new_release.milestones.map { |m| m.title }
+
+ # Right now the milestones are returned in a non-deterministic order.
+ # `match_array` should be updated to `eq` once
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/259012 is addressed.
+ expect(actual_milestone_titles).to match_array(expected_milestone_titles)
+ end
+
+ describe 'asset links' do
+ let(:expected_link) { assets[:links].first }
+ let(:new_link) { new_release.links.first }
+
+ it 'creates a single asset link' do
+ expect(new_release.links.size).to eq(1)
+ end
+
+ it 'creates the link with the correct name' do
+ expect(new_link.name).to eq(expected_link[:name])
+ end
+
+ it 'creates the link with the correct url' do
+ expect(new_link.url).to eq(expected_link[:url])
+ end
+
+ it 'creates the link with the correct link type' do
+ expect(new_link.link_type).to eq(expected_link[:link_type])
+ end
+
+ it 'creates the link with the correct direct filepath' do
+ expect(new_link.filepath).to eq(expected_link[:filepath])
+ end
+ end
+ end
+
+ context "when the current user doesn't have access to create releases" do
+ let(:current_user) { reporter }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/terraform/state/delete_spec.rb b/spec/graphql/mutations/terraform/state/delete_spec.rb
new file mode 100644
index 00000000000..313a85a4bac
--- /dev/null
+++ b/spec/graphql/mutations/terraform/state/delete_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Terraform::State::Delete do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:state) { create(:terraform_state) }
+
+ let(:mutation) do
+ described_class.new(
+ object: double,
+ context: { current_user: user },
+ field: double
+ )
+ end
+
+ it { expect(described_class.graphql_name).to eq('TerraformStateDelete') }
+ it { expect(described_class).to require_graphql_authorizations(:admin_terraform_state) }
+
+ describe '#resolve' do
+ let(:global_id) { state.to_global_id }
+
+ subject { mutation.resolve(id: global_id) }
+
+ context 'user does not have permission' do
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect { state.reload }.not_to raise_error
+ end
+ end
+
+ context 'user has permission' do
+ before do
+ state.project.add_maintainer(user)
+ end
+
+ it 'deletes the state', :aggregate_failures do
+ expect do
+ expect(subject).to eq(errors: [])
+ end.to change { ::Terraform::State.count }.by(-1)
+
+ expect { state.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'with invalid params' do
+ let(:global_id) { user.to_global_id }
+
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect { state.reload }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/terraform/state/lock_spec.rb b/spec/graphql/mutations/terraform/state/lock_spec.rb
new file mode 100644
index 00000000000..c83563040fd
--- /dev/null
+++ b/spec/graphql/mutations/terraform/state/lock_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Terraform::State::Lock do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:state) { create(:terraform_state) }
+
+ let(:mutation) do
+ described_class.new(
+ object: double,
+ context: { current_user: user },
+ field: double
+ )
+ end
+
+ it { expect(described_class.graphql_name).to eq('TerraformStateLock') }
+ it { expect(described_class).to require_graphql_authorizations(:admin_terraform_state) }
+
+ describe '#resolve' do
+ let(:global_id) { state.to_global_id }
+
+ subject { mutation.resolve(id: global_id) }
+
+ context 'user does not have permission' do
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).not_to be_locked
+ end
+ end
+
+ context 'user has permission' do
+ before do
+ state.project.add_maintainer(user)
+ end
+
+ it 'locks the state', :aggregate_failures do
+ expect(subject).to eq(errors: [])
+
+ expect(state.reload).to be_locked
+ expect(state.locked_by_user).to eq(user)
+ expect(state.lock_xid).to be_present
+ expect(state.locked_at).to be_present
+ end
+
+ context 'state is already locked' do
+ let(:locked_by_user) { create(:user) }
+ let(:state) { create(:terraform_state, :locked, locked_by_user: locked_by_user) }
+
+ it 'does not modify the existing lock', :aggregate_failures do
+ expect(subject).to eq(errors: ['state is already locked'])
+
+ expect(state.reload).to be_locked
+ expect(state.locked_by_user).to eq(locked_by_user)
+ end
+ end
+ end
+
+ context 'with invalid params' do
+ let(:global_id) { user.to_global_id }
+
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).not_to be_locked
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/terraform/state/unlock_spec.rb b/spec/graphql/mutations/terraform/state/unlock_spec.rb
new file mode 100644
index 00000000000..4918a1c4abf
--- /dev/null
+++ b/spec/graphql/mutations/terraform/state/unlock_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Terraform::State::Unlock do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:state) { create(:terraform_state, :locked) }
+
+ let(:mutation) do
+ described_class.new(
+ object: double,
+ context: { current_user: user },
+ field: double
+ )
+ end
+
+ it { expect(described_class.graphql_name).to eq('TerraformStateUnlock') }
+ it { expect(described_class).to require_graphql_authorizations(:admin_terraform_state) }
+
+ describe '#resolve' do
+ let(:global_id) { state.to_global_id }
+
+ subject { mutation.resolve(id: global_id) }
+
+ context 'user does not have permission' do
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).to be_locked
+ end
+ end
+
+ context 'user has permission' do
+ before do
+ state.project.add_maintainer(user)
+ end
+
+ it 'unlocks the state', :aggregate_failures do
+ expect(subject).to eq(errors: [])
+ expect(state.reload).not_to be_locked
+ end
+
+ context 'state is already unlocked' do
+ let(:state) { create(:terraform_state) }
+
+ it 'does not modify the state' do
+ expect(subject).to eq(errors: [])
+ expect(state.reload).not_to be_locked
+ end
+ end
+ end
+
+ context 'with invalid params' do
+ let(:global_id) { user.to_global_id }
+
+ it 'raises an error', :aggregate_failures do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect(state.reload).to be_locked
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/todos/create_spec.rb b/spec/graphql/mutations/todos/create_spec.rb
new file mode 100644
index 00000000000..bbb033e2f33
--- /dev/null
+++ b/spec/graphql/mutations/todos/create_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Todos::Create do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ describe '#resolve' do
+ context 'when target does not support todos' do
+ it 'raises error' do
+ current_user = create(:user)
+ mutation = described_class.new(object: nil, context: { current_user: current_user }, field: nil)
+
+ target = create(:milestone)
+
+ expect { mutation.resolve(target_id: global_id_of(target)) }
+ .to raise_error(GraphQL::CoercionError)
+ end
+ end
+
+ context 'with issue as target' do
+ it_behaves_like 'create todo mutation' do
+ let_it_be(:target) { create(:issue) }
+ end
+ end
+
+ context 'with merge request as target' do
+ it_behaves_like 'create todo mutation' do
+ let_it_be(:target) { create(:merge_request) }
+ end
+ end
+
+ context 'with design as target' do
+ before do
+ enable_design_management
+ end
+
+ it_behaves_like 'create todo mutation' do
+ let_it_be(:target) { create(:design) }
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/todos/mark_all_done_spec.rb b/spec/graphql/mutations/todos/mark_all_done_spec.rb
index 2f167164050..f3b6bf52ef7 100644
--- a/spec/graphql/mutations/todos/mark_all_done_spec.rb
+++ b/spec/graphql/mutations/todos/mark_all_done_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Mutations::Todos::MarkAllDone do
expect(todo3.reload.state).to eq('done')
expect(other_user_todo.reload.state).to eq('pending')
- expect(updated_todo_ids).to contain_exactly(global_id_of(todo1), global_id_of(todo3))
+ expect(updated_todo_ids).to contain_exactly(todo1.id, todo3.id)
expect(todos).to contain_exactly(todo1, todo3)
end
diff --git a/spec/graphql/mutations/todos/restore_many_spec.rb b/spec/graphql/mutations/todos/restore_many_spec.rb
index 59995e33f2d..dc10355ef22 100644
--- a/spec/graphql/mutations/todos/restore_many_spec.rb
+++ b/spec/graphql/mutations/todos/restore_many_spec.rb
@@ -24,11 +24,11 @@ RSpec.describe Mutations::Todos::RestoreMany do
expect(todo2.reload.state).to eq('pending')
expect(other_user_todo.reload.state).to eq('done')
- todo_ids = result[:updated_ids]
- expect(todo_ids.size).to eq(1)
- expect(todo_ids.first).to eq(todo1.to_global_id.to_s)
-
- expect(result[:todos]).to contain_exactly(todo1)
+ expect(result).to match(
+ errors: be_empty,
+ updated_ids: contain_exactly(todo1.id),
+ todos: contain_exactly(todo1)
+ )
end
it 'handles a todo which is already pending as expected' do
@@ -36,8 +36,11 @@ RSpec.describe Mutations::Todos::RestoreMany do
expect_states_were_not_changed
- expect(result[:updated_ids]).to eq([])
- expect(result[:todos]).to be_empty
+ expect(result).to match(
+ errors: be_empty,
+ updated_ids: be_empty,
+ todos: be_empty
+ )
end
it 'ignores requests for todos which do not belong to the current user' do
@@ -61,7 +64,7 @@ RSpec.describe Mutations::Todos::RestoreMany do
expect(result[:updated_ids].size).to eq(2)
returned_todo_ids = result[:updated_ids]
- expect(returned_todo_ids).to contain_exactly(todo1.to_global_id.to_s, todo4.to_global_id.to_s)
+ expect(returned_todo_ids).to contain_exactly(todo1.id, todo4.id)
expect(result[:todos]).to contain_exactly(todo1, todo4)
expect(todo1.reload.state).to eq('pending')