diff options
Diffstat (limited to 'spec/graphql/mutations')
9 files changed, 248 insertions, 54 deletions
diff --git a/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb b/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb index f47f1b9869e..2eccfd3409f 100644 --- a/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb +++ b/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb @@ -6,7 +6,6 @@ RSpec.describe Mutations::Ci::Runner::BulkDelete do include GraphqlHelpers let_it_be(:admin_user) { create(:user, :admin) } - let_it_be(:user) { create(:user) } let(:current_ctx) { { current_user: user } } @@ -19,24 +18,15 @@ RSpec.describe Mutations::Ci::Runner::BulkDelete do sync(resolve(described_class, args: mutation_params, ctx: current_ctx)) end - context 'when the user cannot admin the runner' do - let(:runner) { create(:ci_runner) } - let(:mutation_params) do - { ids: [runner.to_global_id] } - end - - it 'generates an error' do - expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) { response } - end - end - context 'when user can delete runners' do + let_it_be(:group) { create(:group) } + let(:user) { admin_user } let!(:runners) do - create_list(:ci_runner, 2, :instance) + create_list(:ci_runner, 2, :group, groups: [group]) end - context 'when required arguments are missing' do + context 'when runner IDs are missing' do let(:mutation_params) { {} } context 'when admin mode is enabled', :enable_admin_mode do @@ -47,43 +37,48 @@ RSpec.describe Mutations::Ci::Runner::BulkDelete do end context 'with runners specified by id' do - let(:mutation_params) do + let!(:mutation_params) do { ids: runners.map(&:to_global_id) } end context 'when admin mode is enabled', :enable_admin_mode do it 'deletes runners', :aggregate_failures do - expect_next_instance_of( - ::Ci::Runners::BulkDeleteRunnersService, { runners: runners } - ) do |service| - expect(service).to receive(:execute).once.and_call_original - end - expect { response }.to change { Ci::Runner.count }.by(-2) expect(response[:errors]).to be_empty end + end - context 'when runner list is is above limit' do - before do - stub_const('::Ci::Runners::BulkDeleteRunnersService::RUNNER_LIMIT', 1) - end - - it 'only deletes up to the defined limit', :aggregate_failures do - expect { response }.to change { Ci::Runner.count } - .by(-::Ci::Runners::BulkDeleteRunnersService::RUNNER_LIMIT) - expect(response[:errors]).to be_empty - end + it 'ignores unknown keys from service response payload', :aggregate_failures do + expect_next_instance_of( + ::Ci::Runners::BulkDeleteRunnersService, { runners: runners, current_user: user } + ) do |service| + expect(service).to receive(:execute).once.and_return( + ServiceResponse.success( + payload: { + extra_key: 'extra_value', + deleted_count: 10, + deleted_ids: (1..10).to_a, + errors: [] + })) end + + expect(response).not_to include(extra_key: 'extra_value') end + end + end - context 'when admin mode is disabled', :aggregate_failures do - it 'returns error', :aggregate_failures do - expect do - expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do - response - end - end.not_to change { Ci::Runner.count } - end + context 'when the user cannot delete the runner' do + let(:runner) { create(:ci_runner) } + let!(:mutation_params) do + { ids: [runner.to_global_id] } + end + + context 'when user is admin and admin mode is not enabled' do + let(:user) { admin_user } + + it 'returns error', :aggregate_failures do + expect { response }.not_to change { Ci::Runner.count } + expect(response[:errors]).to match_array("User does not have permission to delete any of the runners") end end end diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb index ee65be1e085..098b7ac6aa4 100644 --- a/spec/graphql/mutations/ci/runner/update_spec.rb +++ b/spec/graphql/mutations/ci/runner/update_spec.rb @@ -7,8 +7,10 @@ RSpec.describe Mutations::Ci::Runner::Update do let_it_be(:user) { create(:user) } let_it_be(:project1) { create(:project) } - let_it_be(:runner) do - create(:ci_runner, :project, projects: [project1], active: true, locked: false, run_untagged: true) + let_it_be(:project2) { create(:project) } + + let(:runner) do + create(:ci_runner, :project, projects: [project1, project2], active: true, locked: false, run_untagged: true) end let(:current_ctx) { { current_user: user } } @@ -79,14 +81,14 @@ RSpec.describe Mutations::Ci::Runner::Update do end context 'with associatedProjects argument' do - let_it_be(:project2) { create(:project) } + let_it_be(:project3) { create(:project) } context 'with id set to project runner' do let(:mutation_params) do { id: runner.to_global_id, description: 'updated description', - associated_projects: [project2.to_global_id.to_s] + associated_projects: [project3.to_global_id.to_s] } end @@ -96,7 +98,7 @@ RSpec.describe Mutations::Ci::Runner::Update do { runner: runner, current_user: admin_user, - project_ids: [project2.id] + project_ids: [project3.id] } ) do |service| expect(service).to receive(:execute).and_call_original @@ -110,7 +112,7 @@ RSpec.describe Mutations::Ci::Runner::Update do expect(response[:runner]).to be_an_instance_of(Ci::Runner) expect(response[:runner]).to have_attributes(expected_attributes) expect(runner.reload).to have_attributes(expected_attributes) - expect(runner.projects).to match_array([project1, project2]) + expect(runner.projects).to match_array([project1, project3]) end context 'with user not allowed to assign runner' do @@ -124,7 +126,7 @@ RSpec.describe Mutations::Ci::Runner::Update do { runner: runner, current_user: admin_user, - project_ids: [project2.id] + project_ids: [project3.id] } ) do |service| expect(service).to receive(:execute).and_call_original @@ -137,11 +139,39 @@ RSpec.describe Mutations::Ci::Runner::Update do expect(response[:errors]).to match_array(['user not allowed to assign runner']) expect(response[:runner]).to be_nil expect(runner.reload).not_to have_attributes(expected_attributes) - expect(runner.projects).to match_array([project1]) + expect(runner.projects).to match_array([project1, project2]) end end end + context 'with an empty list of projects' do + let(:mutation_params) do + { + id: runner.to_global_id, + associated_projects: [] + } + end + + it 'removes project relationships', :aggregate_failures do + expect_next_instance_of( + ::Ci::Runners::SetRunnerAssociatedProjectsService, + { + runner: runner, + current_user: admin_user, + project_ids: [] + } + ) do |service| + expect(service).to receive(:execute).and_call_original + end + + response + + expect(response[:errors]).to be_empty + expect(response[:runner]).to be_an_instance_of(Ci::Runner) + expect(runner.reload.projects).to contain_exactly(project1) + end + end + context 'with id set to instance runner' do let(:instance_runner) { create(:ci_runner, :instance) } let(:mutation_params) do diff --git a/spec/graphql/mutations/commits/create_spec.rb b/spec/graphql/mutations/commits/create_spec.rb index fd0c2c46b2e..2c452410cca 100644 --- a/spec/graphql/mutations/commits/create_spec.rb +++ b/spec/graphql/mutations/commits/create_spec.rb @@ -179,7 +179,7 @@ RSpec.describe Mutations::Commits::Create do it 'returns errors' do expect(mutated_commit).to be_nil - expect(subject[:errors].to_s).to match(/3:UserCommitFiles: empty CommitMessage/) + expect(subject[:errors].to_s).to match(/empty CommitMessage/) end end diff --git a/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb b/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb index 6bed3a752ed..3198419fb81 100644 --- a/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb +++ b/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Mutations::ResolvesGroup do end end - let(:context) { double } + let(:context) { {} } subject(:mutation) { mutation_class.new(object: nil, context: context, field: nil) } diff --git a/spec/graphql/mutations/container_repositories/destroy_spec.rb b/spec/graphql/mutations/container_repositories/destroy_spec.rb index 97da7846339..9f3ff8da80b 100644 --- a/spec/graphql/mutations/container_repositories/destroy_spec.rb +++ b/spec/graphql/mutations/container_repositories/destroy_spec.rb @@ -20,11 +20,10 @@ RSpec.describe Mutations::ContainerRepositories::Destroy do end shared_examples 'destroying the container repository' do - it 'destroys the container repistory' do + it 'marks the repository as delete_scheduled' 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(DeleteContainerRepositoryWorker).not_to receive(:perform_async) expect { subject }.to change { ::Packages::Event.count }.by(1) expect(container_repository.reload.delete_scheduled?).to be true @@ -56,6 +55,23 @@ RSpec.describe Mutations::ContainerRepositories::Destroy do it_behaves_like params[:shared_examples_name] end + + context 'with container_registry_delete_repository_with_cron_worker disabled' do + before do + project.add_maintainer(user) + stub_feature_flags(container_registry_delete_repository_with_cron_worker: false) + end + + it 'enqueues a removal job' 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 end end end diff --git a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb index 9254d84b29c..aab21776a99 100644 --- a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb +++ b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb @@ -6,6 +6,9 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Create do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } let_it_be(:incident) { create(:incident, project: project) } + let_it_be(:timeline_event_tag) do + create(:incident_management_timeline_event_tag, project: project, name: 'Test tag 1') + end let(:args) { { note: 'note', occurred_at: Time.current } } @@ -39,6 +42,104 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Create do it_behaves_like 'responding with an incident timeline errors', errors: ["Occurred at can't be blank and Timeline text can't be blank"] end + + context 'when timeline event tags are passed' do + let(:args) do + { + note: 'note', + occurred_at: Time.current, + timeline_event_tag_names: [timeline_event_tag.name.to_s] + } + end + + it_behaves_like 'creating an incident timeline event' + end + + context 'when predefined tags are passed' do + let(:args) do + { + note: 'note', + occurred_at: Time.current, + timeline_event_tag_names: ['Start time'] + } + end + + it_behaves_like 'creating an incident timeline event' + + it 'creates and sets the tag on the event' do + timeline_event = resolve[:timeline_event] + + expect(timeline_event.timeline_event_tags.by_names(['Start time']).count).to eq 1 + end + end + + context 'when predefined tags exist' do + let_it_be(:end_time_tag) do + create(:incident_management_timeline_event_tag, project: project, name: 'End time') + end + + let(:args) do + { + note: 'note', + occurred_at: Time.current, + timeline_event_tag_names: ['End time'] + } + end + + it 'does not create a new tag' do + expect { resolve }.not_to change(IncidentManagement::TimelineEventTag, :count) + end + end + + context 'when same tags are tried to be assigned to same timeline event' do + let(:args) do + { + note: 'note', + occurred_at: Time.current, + timeline_event_tag_names: ['Start time', 'Start time'] + } + end + + it 'only assigns the tag once on the event' do + timeline_event = resolve[:timeline_event] + + expect(timeline_event.timeline_event_tags.by_names(['Start time']).count).to eq(1) + expect(timeline_event.timeline_event_tags.count).to eq(1) + end + end + + context 'with case-insentive tags' do + let(:args) do + { + note: 'note', + occurred_at: Time.current, + timeline_event_tag_names: ['tESt tAg 1'] + } + end + + it 'sets the tag on the event' do + timeline_event = resolve[:timeline_event] + + expect(timeline_event.timeline_event_tags.by_names(['Test tag 1']).count).to eq(1) + end + end + + context 'when non-existing tags are passed' do + let(:args) do + { + note: 'note', + occurred_at: Time.current, + timeline_event_tag_names: ['other time'] + } + end + + it_behaves_like 'responding with an incident timeline errors', + errors: ["Following tags don't exist: [\"other time\"]"] + + it 'does not create the timeline event' do + expect { resolve }.not_to change(IncidentManagement::TimelineEvent, :count) + end + end end it_behaves_like 'failing to create an incident timeline event' diff --git a/spec/graphql/mutations/incident_management/timeline_event_tag/create_spec.rb b/spec/graphql/mutations/incident_management/timeline_event_tag/create_spec.rb new file mode 100644 index 00000000000..57a32f7e4bc --- /dev/null +++ b/spec/graphql/mutations/incident_management/timeline_event_tag/create_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::IncidentManagement::TimelineEventTag::Create do + let_it_be(:current_user) { create(:user) } + let_it_be_with_reload(:project) { create(:project) } + + let(:args) { { name: 'Test tag 1' } } + + before do + project.add_maintainer(current_user) + end + + specify { expect(described_class).to require_graphql_authorizations(:admin_incident_management_timeline_event_tag) } + + describe '#resolve' do + subject(:resolve) { mutation_for(project, current_user).resolve(project_path: project.full_path, **args) } + + context 'when user has permission to create timeline event tag' do + it 'adds the tag to the project' do + expect { resolve }.to change(IncidentManagement::TimelineEventTag, :count).by(1) + expect(project.incident_management_timeline_event_tags.by_names(['Test tag 1']).pluck_names) + .to match_array(['Test tag 1']) + end + end + + context 'when TimelineEventTags::CreateService responds with an error' do + let(:args) { {} } + + it 'returns errors' do + expect(resolve).to eq(timeline_event_tag: nil, errors: ["Name can't be blank and Name is invalid"]) + end + end + + context 'when user has no permissions to create tags on a project' do + before do + project.add_developer(current_user) + end + + it 'raises an error' do + expect { resolve }.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/security/ci_configuration/base_security_analyzer_spec.rb b/spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb index 668768189df..c081f9f0cd2 100644 --- a/spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb +++ b/spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb @@ -11,6 +11,6 @@ RSpec.describe Mutations::Security::CiConfiguration::BaseSecurityAnalyzer do project = create(:project, :public, :repository) project.add_developer(user) - expect { mutation.resolve(project_path: project.full_path ) }.to raise_error(NotImplementedError) + expect { mutation.resolve(project_path: project.full_path) }.to raise_error(NotImplementedError) end end diff --git a/spec/graphql/mutations/todos/restore_many_spec.rb b/spec/graphql/mutations/todos/restore_many_spec.rb index d43f1c8a2e9..3235be8486e 100644 --- a/spec/graphql/mutations/todos/restore_many_spec.rb +++ b/spec/graphql/mutations/todos/restore_many_spec.rb @@ -80,7 +80,7 @@ RSpec.describe Mutations::Todos::RestoreMany do end def restore_mutation(todos) - mutation.resolve(ids: todos.map { |todo| global_id_of(todo) } ) + mutation.resolve(ids: todos.map { |todo| global_id_of(todo) }) end def expect_states_were_not_changed |