diff options
Diffstat (limited to 'spec/graphql')
18 files changed, 301 insertions, 91 deletions
diff --git a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb index e6a7434d579..47ee338ad34 100644 --- a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb +++ b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb @@ -28,6 +28,7 @@ RSpec.describe Mutations::AlertManagement::CreateAlertIssue do end it_behaves_like 'an incident management tracked event', :incident_management_incident_created + it_behaves_like 'an incident management tracked event', :incident_management_alert_create_incident end context 'when CreateAlertIssue responds with an error' do diff --git a/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb b/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb index f74f9186743..acd7070d0d3 100644 --- a/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb +++ b/spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Mutations::AlertManagement::HttpIntegration::Destroy do specify { expect(described_class).to require_graphql_authorizations(:admin_operations) } describe '#resolve' do - subject(:resolve) { mutation_for(project, current_user).resolve(args) } + subject(:resolve) { mutation_for(project, current_user).resolve(**args) } context 'user has access to project' do before do 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 index d3ffb2abb47..96974c2aa6f 100644 --- a/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb +++ b/spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Mutations::AlertManagement::HttpIntegration::ResetToken do specify { expect(described_class).to require_graphql_authorizations(:admin_operations) } describe '#resolve' do - subject(:resolve) { mutation_for(project, current_user).resolve(args) } + subject(:resolve) { mutation_for(project, current_user).resolve(**args) } context 'user has sufficient access to project' do before do 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 index 45d92695e06..ddf23909035 100644 --- a/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb +++ b/spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Mutations::AlertManagement::PrometheusIntegration::ResetToken do specify { expect(described_class).to require_graphql_authorizations(:admin_project) } describe '#resolve' do - subject(:resolve) { mutation_for(project, current_user).resolve(args) } + subject(:resolve) { mutation_for(project, current_user).resolve(**args) } context 'user has sufficient access to project' do before do 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 08761ce64c2..8465393f299 100644 --- a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb +++ b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Mutations::AlertManagement::UpdateAlertStatus do specify { expect(described_class).to require_graphql_authorizations(:update_alert_management_alert) } describe '#resolve' do - subject(:resolve) { mutation_for(project, current_user).resolve(args) } + subject(:resolve) { mutation_for(project, current_user).resolve(**args) } context 'user has access to project' do before do diff --git a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb index 71c43ed826c..ded5776b3cb 100644 --- a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb +++ b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb @@ -34,18 +34,18 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do end subject do - mutation.resolve(params.merge(move_params)) + mutation.resolve(**params.merge(move_params)) end describe '#ready?' do it 'raises an error if required arguments are missing' do - expect { mutation.ready?(params) } + expect { mutation.ready?(**params) } .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "At least one of the arguments " \ "fromListId, toListId, afterId or beforeId is required") end it 'raises an error if only one of fromListId and toListId is present' do - expect { mutation.ready?(params.merge(from_list_id: list1.id)) } + expect { mutation.ready?(**params.merge(from_list_id: list1.id)) } .to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'Both fromListId and toListId must be present' ) diff --git a/spec/graphql/mutations/boards/lists/create_spec.rb b/spec/graphql/mutations/boards/lists/create_spec.rb index b1fe9911c7b..7a638d11ed3 100644 --- a/spec/graphql/mutations/boards/lists/create_spec.rb +++ b/spec/graphql/mutations/boards/lists/create_spec.rb @@ -23,12 +23,12 @@ RSpec.describe Mutations::Boards::Lists::Create do describe '#ready?' do it 'raises an error if required arguments are missing' do - expect { mutation.ready?({ board_id: 'some id' }) } + expect { mutation.ready?(board_id: 'some id') } .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/) end it 'raises an error if too many required arguments are specified' do - expect { mutation.ready?({ board_id: 'some id', backlog: true, label_id: 'some label' }) } + expect { mutation.ready?(board_id: 'some id', backlog: true, label_id: 'some label') } .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/) end end diff --git a/spec/graphql/mutations/concerns/mutations/finds_by_gid_spec.rb b/spec/graphql/mutations/concerns/mutations/finds_by_gid_spec.rb new file mode 100644 index 00000000000..37e0fd611e4 --- /dev/null +++ b/spec/graphql/mutations/concerns/mutations/finds_by_gid_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::FindsByGid do + include GraphqlHelpers + + let(:mutation_class) do + Class.new(Mutations::BaseMutation) do + authorize :read_user + + include Mutations::FindsByGid + end + end + + let(:query) { double('Query', schema: GitlabSchema) } + let(:context) { GraphQL::Query::Context.new(query: query, object: nil, values: { current_user: user }) } + let(:user) { create(:user) } + let(:gid) { user.to_global_id } + + subject(:mutation) { mutation_class.new(object: nil, context: context, field: nil) } + + it 'calls GitlabSchema.find_by_gid to find objects during authorized_find!' do + expect(mutation.authorized_find!(id: gid)).to eq(user) + end +end diff --git a/spec/graphql/mutations/container_expiration_policies/update_spec.rb b/spec/graphql/mutations/container_expiration_policies/update_spec.rb index 9c6016e0af4..e22fb951172 100644 --- a/spec/graphql/mutations/container_expiration_policies/update_spec.rb +++ b/spec/graphql/mutations/container_expiration_policies/update_spec.rb @@ -14,7 +14,7 @@ RSpec.describe Mutations::ContainerExpirationPolicies::Update do specify { expect(described_class).to require_graphql_authorizations(:destroy_container_image) } describe '#resolve' do - subject { described_class.new(object: project, context: { current_user: user }, field: nil).resolve(params) } + subject { described_class.new(object: project, context: { current_user: user }, field: nil).resolve(**params) } RSpec.shared_examples 'returning a success' do it 'returns the container expiration policy with no errors' do diff --git a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb index 2e5d41a8f1e..162b1249ab5 100644 --- a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb +++ b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Mutations::Discussions::ToggleResolve do describe '#resolve' do subject do - mutation.resolve({ id: id_arg, resolve: resolve_arg }) + mutation.resolve(id: id_arg, resolve: resolve_arg) end let(:id_arg) { discussion.to_global_id.to_s } diff --git a/spec/graphql/mutations/issues/create_spec.rb b/spec/graphql/mutations/issues/create_spec.rb index 57658f6b358..422ad40a9cb 100644 --- a/spec/graphql/mutations/issues/create_spec.rb +++ b/spec/graphql/mutations/issues/create_spec.rb @@ -51,7 +51,7 @@ RSpec.describe Mutations::Issues::Create do project.add_guest(assignee2) end - subject { mutation.resolve(mutation_params) } + subject { mutation.resolve(**mutation_params) } context 'when the user does not have permission to create an issue' do it 'raises an error' do @@ -117,7 +117,7 @@ RSpec.describe Mutations::Issues::Create do end it 'raises exception when mutually exclusive params are given' do - expect { mutation.ready?(mutation_params) } + expect { mutation.ready?(**mutation_params) } .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/) end end @@ -128,7 +128,7 @@ RSpec.describe Mutations::Issues::Create do end it 'raises exception when mutually exclusive params are given' do - expect { mutation.ready?(mutation_params) } + expect { mutation.ready?(**mutation_params) } .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /to resolve a discussion please also provide `merge_request_to_resolve_discussions_of` parameter/) end end @@ -139,7 +139,7 @@ RSpec.describe Mutations::Issues::Create do end it 'raises exception when mutually exclusive params are given' do - expect { mutation.ready?(mutation_params) }.not_to raise_error + expect { mutation.ready?(**mutation_params) }.not_to raise_error end end end diff --git a/spec/graphql/mutations/labels/create_spec.rb b/spec/graphql/mutations/labels/create_spec.rb index 8b284816d63..b2dd94f31bb 100644 --- a/spec/graphql/mutations/labels/create_spec.rb +++ b/spec/graphql/mutations/labels/create_spec.rb @@ -58,7 +58,7 @@ RSpec.describe Mutations::Labels::Create do end describe '#ready?' do - subject { mutation.ready?(attributes.merge(extra_params)) } + 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' } } diff --git a/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb index 8c22e1a1cb6..d88b196cbff 100644 --- a/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb +++ b/spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Mutations::Notes::RepositionImageDiffNote do describe '#resolve' do subject do - mutation.resolve({ note: note, position: new_position }) + mutation.resolve(note: note, position: new_position) end let_it_be(:noteable) { create(:merge_request) } diff --git a/spec/graphql/mutations/releases/update_spec.rb b/spec/graphql/mutations/releases/update_spec.rb new file mode 100644 index 00000000000..0406e9c96f3 --- /dev/null +++ b/spec/graphql/mutations/releases/update_spec.rb @@ -0,0 +1,232 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Releases::Update 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_it_be(:tag) { 'v1.1.0'} + let_it_be(:name) { 'Version 1.0'} + let_it_be(:description) { 'The first release :rocket:' } + let_it_be(:released_at) { Time.parse('2018-12-10').utc } + let_it_be(:created_at) { Time.parse('2018-11-05').utc } + let_it_be(:milestones) { [milestone_12_3.title, milestone_12_4.title] } + + let_it_be(:release) do + create(:release, project: project, tag: tag, name: name, + description: description, released_at: released_at, + created_at: created_at, milestones: [milestone_12_3, milestone_12_4]) + end + + let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) } + + let(:mutation_arguments) do + { + project_path: project.full_path, + tag: tag + } + end + + around do |example| + freeze_time { example.run } + end + + before do + project.add_reporter(reporter) + project.add_developer(developer) + end + + shared_examples 'no changes to the release except for the' do |except_for| + it 'does not change other release properties' do + expect(updated_release.project).to eq(project) + expect(updated_release.tag).to eq(tag) + + expect(updated_release.name).to eq(name) unless except_for == :name + expect(updated_release.description).to eq(description) unless except_for == :description + expect(updated_release.released_at).to eq(released_at) unless except_for == :released_at + + # Right now the milestones are returned in a non-deterministic order. + # Because of this, we need to allow for milestones to be returned in any order. + # Once https://gitlab.com/gitlab-org/gitlab/-/issues/259012 has been + # fixed, this can be updated to expect a specific order. + expect(updated_release.milestones).to match_array([milestone_12_3, milestone_12_4]) unless except_for == :milestones + end + end + + shared_examples 'validation error with message' do |message| + it 'returns the updated release as nil' do + expect(updated_release).to be_nil + end + + it 'returns a validation error' do + expect(subject[:errors]).to eq([message]) + end + end + + describe '#ready?' do + let(:current_user) { developer } + + subject(:ready) do + mutation.ready?(**mutation_arguments) + end + + context 'when released_at is included as an argument but is passed nil' do + let(:mutation_arguments) { super().merge(released_at: nil) } + + it 'raises a validation error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'if the releasedAt argument is provided, it cannot be null') + end + end + + context 'when milestones is included as an argument but is passed nil' do + let(:mutation_arguments) { super().merge(milestones: nil) } + + it 'raises a validation error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'if the milestones argument is provided, it cannot be null') + end + end + end + + describe '#resolve' do + subject(:resolve) do + mutation.resolve(**mutation_arguments) + end + + let(:updated_release) { subject[:release] } + + context 'when the current user has access to create releases' do + let(:current_user) { developer } + + context 'name' do + let(:mutation_arguments) { super().merge(name: updated_name) } + + context 'when a new name is provided' do + let(:updated_name) { 'Updated name' } + + it 'updates the name' do + expect(updated_release.name).to eq(updated_name) + end + + it_behaves_like 'no changes to the release except for the', :name + end + + context 'when nil is provided' do + let(:updated_name) { nil } + + it 'updates the name to be the tag name' do + expect(updated_release.name).to eq(tag) + end + + it_behaves_like 'no changes to the release except for the', :name + end + end + + context 'description' do + let(:mutation_arguments) { super().merge(description: updated_description) } + + context 'when a new description is provided' do + let(:updated_description) { 'Updated description' } + + it 'updates the description' do + expect(updated_release.description).to eq(updated_description) + end + + it_behaves_like 'no changes to the release except for the', :description + end + + context 'when nil is provided' do + let(:updated_description) { nil } + + it 'updates the description to nil' do + expect(updated_release.description).to eq(nil) + end + + it_behaves_like 'no changes to the release except for the', :description + end + end + + context 'released_at' do + let(:mutation_arguments) { super().merge(released_at: updated_released_at) } + + context 'when a new released_at is provided' do + let(:updated_released_at) { Time.parse('2020-12-10').utc } + + it 'updates the released_at' do + expect(updated_release.released_at).to eq(updated_released_at) + end + + it_behaves_like 'no changes to the release except for the', :released_at + end + end + + context 'milestones' do + let(:mutation_arguments) { super().merge(milestones: updated_milestones) } + + context 'when a new set of milestones is provided provided' do + let(:updated_milestones) { [milestone_12_3.title] } + + it 'updates the milestone associations' do + expect(updated_release.milestones).to eq([milestone_12_3]) + end + + it_behaves_like 'no changes to the release except for the', :milestones + end + + context 'when an empty array is provided' do + let(:updated_milestones) { [] } + + it 'removes all milestone associations' do + expect(updated_release.milestones).to eq([]) + end + + it_behaves_like 'no changes to the release except for the', :milestones + end + + context 'when a non-existent milestone title is provided' do + let(:updated_milestones) { ['not real'] } + + it_behaves_like 'validation error with message', 'Milestone(s) not found: not real' + end + + context 'when a milestone title from a different project is provided' do + let(:milestone_in_different_project) { create(:milestone, title: 'milestone in different project') } + let(:updated_milestones) { [milestone_in_different_project.title] } + + it_behaves_like 'validation error with message', 'Milestone(s) not found: milestone in different project' + end + end + + context 'validation' do + context 'when no updated fields are provided' do + it_behaves_like 'validation error with message', 'params is empty' + end + + context 'when the tag does not exist' do + let(:mutation_arguments) { super().merge(tag: 'not-a-real-tag') } + + it_behaves_like 'validation error with message', 'Tag does not exist' + end + + context 'when the project does not exist' do + let(:mutation_arguments) { super().merge(project_path: 'not/a/real/path') } + + it 'raises an error' 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 + end + end + + context "when the current user doesn't have access to update releases" do + let(:current_user) { reporter } + + it 'raises an error' 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 + end +end diff --git a/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb b/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb index bfb3ce91d58..96ca679620d 100644 --- a/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb +++ b/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb @@ -50,7 +50,7 @@ RSpec.describe Resolvers::ProjectMergeRequestsResolver do end end - def resolve_mr(project, args, resolver: described_class, user: current_user) + def resolve_mr(project, resolver: described_class, user: current_user, **args) resolve(resolver, obj: project, args: args, ctx: { current_user: user }) end end diff --git a/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb deleted file mode 100644 index ad59cb6b95e..00000000000 --- a/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Resolvers::Projects::JiraImportsResolver do - include GraphqlHelpers - - specify do - expect(described_class).to have_nullable_graphql_type(Types::JiraImportType.connection_type) - end - - describe '#resolve' do - let_it_be(:user) { create(:user) } - let_it_be(:project, reload: true) { create(:project, :public) } - - context 'when project does not have Jira imports' do - let(:current_user) { user } - - context 'when user cannot read Jira imports' do - context 'when anonymous user' do - let(:current_user) { nil } - - it_behaves_like 'no Jira import access' - end - end - - context 'when user can read Jira import data' do - before do - project.add_guest(user) - end - - it_behaves_like 'no Jira import data present' - - it 'does not raise access error' do - expect do - resolve_imports - end.not_to raise_error - end - end - end - - context 'when project has Jira imports' do - let_it_be(:current_user) { user } - let_it_be(:jira_import1) { create(:jira_import_state, :finished, project: project, jira_project_key: 'AA', created_at: 2.days.ago) } - let_it_be(:jira_import2) { create(:jira_import_state, :finished, project: project, jira_project_key: 'BB', created_at: 5.days.ago) } - - context 'when user cannot read Jira imports' do - context 'when anonymous user' do - let(:current_user) { nil } - - it_behaves_like 'no Jira import access' - end - end - - context 'when user can access Jira imports' do - before do - project.add_guest(user) - end - - it 'returns Jira imports sorted ascending by created_at time' do - imports = resolve_imports - - expect(imports.size).to eq 2 - expect(imports.map(&:jira_project_key)).to eq %w(BB AA) - end - end - end - end - - def resolve_imports(args = {}, context = { current_user: current_user }) - resolve(described_class, obj: project, args: args, ctx: context) - end -end diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index be579e92fb3..2b566aee9fc 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['Project'] do + include GraphqlHelpers + specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Project) } specify { expect(described_class.graphql_name).to eq('Project') } @@ -163,4 +165,25 @@ RSpec.describe GitlabSchema.types['Project'] do end it_behaves_like 'a GraphQL type with labels' + + describe 'jira_imports' do + subject { resolve_field(:jira_imports, project) } + + let_it_be(:project) { create(:project, :public) } + + context 'when project has Jira imports' do + let_it_be(:jira_import1) { create(:jira_import_state, :finished, project: project, jira_project_key: 'AA', created_at: 2.days.ago) } + let_it_be(:jira_import2) { create(:jira_import_state, :finished, project: project, jira_project_key: 'BB', created_at: 5.days.ago) } + + it 'retrieves the imports' do + expect(subject).to contain_exactly(jira_import1, jira_import2) + end + end + + context 'when project does not have Jira imports' do + it 'returns an empty result' do + expect(subject).to be_empty + end + end + end end diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb index c8953d9ccb7..4e20efe40d6 100644 --- a/spec/graphql/types/user_type_spec.rb +++ b/spec/graphql/types/user_type_spec.rb @@ -21,6 +21,7 @@ RSpec.describe GitlabSchema.types['User'] do todos state status + location authoredMergeRequests assignedMergeRequests groupMemberships |