diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-18 20:02:30 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-18 20:02:30 +0000 |
commit | 41fe97390ceddf945f3d967b8fdb3de4c66b7dea (patch) | |
tree | 9c8d89a8624828992f06d892cd2f43818ff5dcc8 /spec/graphql | |
parent | 0804d2dc31052fb45a1efecedc8e06ce9bc32862 (diff) | |
download | gitlab-ce-14.9.0-rc42.tar.gz |
Add latest changes from gitlab-org/gitlab@14-9-stable-eev14.9.0-rc42
Diffstat (limited to 'spec/graphql')
74 files changed, 923 insertions, 308 deletions
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 dd9305d2197..11c0fa44110 100644 --- a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb +++ b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb @@ -43,11 +43,10 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do context "when we only pass #{arg_name}" do let(:move_params) { { arg_name => list1.id } } - it 'raises an error' do - expect { subject }.to raise_error( - Gitlab::Graphql::Errors::ArgumentError, - 'Both fromListId and toListId must be present' - ) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'Both fromListId and toListId must be present') do + subject + end end end end @@ -55,11 +54,10 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do context 'when required arguments are missing' do let(:move_params) { {} } - it 'raises an error' do - expect { subject }.to raise_error( - Gitlab::Graphql::Errors::ArgumentError, - "At least one of the arguments fromListId, toListId, afterId or beforeId is required" - ) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'At least one of the arguments fromListId, toListId, afterId or beforeId is required') do + subject + end end end diff --git a/spec/graphql/mutations/ci/runner/delete_spec.rb b/spec/graphql/mutations/ci/runner/delete_spec.rb index b53ee30f826..c0f979e43cc 100644 --- a/spec/graphql/mutations/ci/runner/delete_spec.rb +++ b/spec/graphql/mutations/ci/runner/delete_spec.rb @@ -6,8 +6,9 @@ RSpec.describe Mutations::Ci::Runner::Delete do include GraphqlHelpers let_it_be(:runner) { create(:ci_runner) } + let_it_be(:admin_user) { create(:user, :admin) } + let_it_be(:user) { create(:user) } - let(:user) { create(:user) } let(:current_ctx) { { current_user: user } } let(:mutation_params) do @@ -22,15 +23,29 @@ RSpec.describe Mutations::Ci::Runner::Delete do end context 'when the user cannot admin the runner' do - it 'raises an error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end + end + + context 'with more than one associated project' do + let!(:project) { create(:project, creator_id: user.id) } + let!(:project2) { create(:project, creator_id: user.id) } + let!(:two_projects_runner) { create(:ci_runner, :project, description: 'Two projects runner', projects: [project, project2]) } + + it 'raises an error' do + mutation_params[:id] = two_projects_runner.to_global_id + + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end end end context 'with invalid params' do - it 'raises an error' do - mutation_params[:id] = "invalid-id" + let(:mutation_params) { { id: "invalid-id" } } + it 'raises an error' do expect { subject }.to raise_error(::GraphQL::CoercionError) end end @@ -44,6 +59,8 @@ RSpec.describe Mutations::Ci::Runner::Delete do end context 'when user can delete owned runner' do + let_it_be(:user) { create(:user) } + let!(:project) { create(:project, creator_id: user.id) } let!(:project_runner) { create(:ci_runner, :project, description: 'Project runner', projects: [project]) } @@ -52,10 +69,12 @@ RSpec.describe Mutations::Ci::Runner::Delete do end context 'with one associated project' do - it 'deletes runner' do - mutation_params[:id] = project_runner.to_global_id + let(:mutation_params) do + { id: project_runner.to_global_id } + end - expect_next_instance_of(::Ci::UnregisterRunnerService, project_runner) do |service| + it 'deletes runner' do + expect_next_instance_of(::Ci::Runners::UnregisterRunnerService, project_runner, current_ctx[:current_user]) do |service| expect(service).to receive(:execute).once.and_call_original end @@ -68,28 +87,45 @@ RSpec.describe Mutations::Ci::Runner::Delete do let!(:project2) { create(:project, creator_id: user.id) } let!(:two_projects_runner) { create(:ci_runner, :project, description: 'Two projects runner', projects: [project, project2]) } - before do - project2.add_maintainer(user) + let(:mutation_params) do + { id: two_projects_runner.to_global_id } end - it 'does not delete project runner' do - mutation_params[:id] = two_projects_runner.to_global_id + context 'with user as admin', :enable_admin_mode do + let(:current_ctx) { { current_user: admin_user } } + + it 'deletes runner' do + expect_next_instance_of(::Ci::Runners::UnregisterRunnerService, two_projects_runner, current_ctx[:current_user]) do |service| + expect(service).to receive(:execute).once.and_call_original + end + + expect { subject }.to change { Ci::Runner.count }.by(-1) + expect(subject[:errors]).to be_empty + end + end + + context 'with user as project maintainer' do + let_it_be(:user) { create(:user) } + + before do + project2.add_maintainer(user) + end - allow_next_instance_of(::Ci::UnregisterRunnerService) do |service| - expect(service).not_to receive(:execute).once + it 'raises error' do + allow_next_instance_of(::Ci::Runners::UnregisterRunnerService) do |service| + expect(service).not_to receive(:execute) + end + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) end - expect { subject }.not_to change { Ci::Runner.count } - expect(subject[:errors]).to contain_exactly("Runner #{two_projects_runner.to_global_id} associated with more than one project") end end end context 'when admin can delete runner', :enable_admin_mode do - let(:admin_user) { create(:user, :admin) } let(:current_ctx) { { current_user: admin_user } } it 'deletes runner' do - expect_next_instance_of(::Ci::UnregisterRunnerService, runner) do |service| + expect_next_instance_of(::Ci::Runners::UnregisterRunnerService, runner, current_ctx[:current_user]) do |service| expect(service).to receive(:execute).once.and_call_original end diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb index 83150c3d7f6..0b3489d37dc 100644 --- a/spec/graphql/mutations/ci/runner/update_spec.rb +++ b/spec/graphql/mutations/ci/runner/update_spec.rb @@ -26,8 +26,10 @@ RSpec.describe Mutations::Ci::Runner::Update do end context 'when the user cannot admin the runner' do - it 'raises an error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end diff --git a/spec/graphql/mutations/release_asset_links/create_spec.rb b/spec/graphql/mutations/release_asset_links/create_spec.rb index eb7cbb4b789..86a6c77fa3f 100644 --- a/spec/graphql/mutations/release_asset_links/create_spec.rb +++ b/spec/graphql/mutations/release_asset_links/create_spec.rb @@ -63,7 +63,9 @@ RSpec.describe Mutations::ReleaseAssetLinks::Create do let!(:protected_tag) { create(:protected_tag, :maintainers_can_create, name: '*', project: project) } it 'has an access error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end end @@ -71,16 +73,20 @@ RSpec.describe Mutations::ReleaseAssetLinks::Create do context "when the user doesn't have access to the project" do let(:current_user) { reporter } - it 'raises an error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end context "when the project doesn't exist" do let(:project_path) { 'project/that/does/not/exist' } - it 'raises an error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end diff --git a/spec/graphql/mutations/saved_replies/create_spec.rb b/spec/graphql/mutations/saved_replies/create_spec.rb new file mode 100644 index 00000000000..5141c537b06 --- /dev/null +++ b/spec/graphql/mutations/saved_replies/create_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::SavedReplies::Create do + let_it_be(:current_user) { create(:user) } + + let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) } + + let(:mutation_arguments) { { name: 'save_reply_name', content: 'Save Reply Content' } } + + describe '#resolve' do + subject(:resolve) do + mutation.resolve(**mutation_arguments) + end + + context 'when feature is disabled' do + before do + stub_feature_flags(saved_replies: false) + end + + it 'raises Gitlab::Graphql::Errors::ResourceNotAvailable' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled') + end + end + + context 'when feature is enabled for current user' do + before do + stub_feature_flags(saved_replies: current_user) + end + + context 'when service fails to create a new saved reply' do + let(:mutation_arguments) { { name: '', content: '' } } + + it { expect(subject[:saved_reply]).to be_nil } + it { expect(subject[:errors]).to match_array(["Content can't be blank", "Name can't be blank", "Name can contain only lowercase letters, digits, '_' and '-'. Must start with a letter, and cannot end with '-' or '_'"]) } + end + + context 'when service successfully creates a new saved reply' do + it { expect(subject[:saved_reply].name).to eq(mutation_arguments[:name]) } + it { expect(subject[:saved_reply].content).to eq(mutation_arguments[:content]) } + it { expect(subject[:errors]).to be_empty } + end + end + end +end diff --git a/spec/graphql/mutations/saved_replies/update_spec.rb b/spec/graphql/mutations/saved_replies/update_spec.rb new file mode 100644 index 00000000000..67c2d1348f7 --- /dev/null +++ b/spec/graphql/mutations/saved_replies/update_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::SavedReplies::Update do + let_it_be(:current_user) { create(:user) } + let_it_be(:saved_reply) { create(:saved_reply, user: current_user) } + + let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) } + + let(:mutation_arguments) { { name: 'save_reply_name', content: 'Save Reply Content' } } + + describe '#resolve' do + subject(:resolve) do + mutation.resolve(id: saved_reply.to_global_id, **mutation_arguments) + end + + context 'when feature is disabled' do + before do + stub_feature_flags(saved_replies: false) + end + + it 'raises Gitlab::Graphql::Errors::ResourceNotAvailable' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled') + end + end + + context 'when feature is enabled for current user' do + before do + stub_feature_flags(saved_replies: current_user) + end + + context 'when service fails to update a new saved reply' do + let(:mutation_arguments) { { name: '', content: '' } } + + it { expect(subject[:saved_reply]).to be_nil } + it { expect(subject[:errors]).to match_array(["Content can't be blank", "Name can't be blank", "Name can contain only lowercase letters, digits, '_' and '-'. Must start with a letter, and cannot end with '-' or '_'"]) } + end + + context 'when service successfully updates the saved reply' do + it { expect(subject[:saved_reply].name).to eq(mutation_arguments[:name]) } + it { expect(subject[:saved_reply].content).to eq(mutation_arguments[:content]) } + it { expect(subject[:errors]).to be_empty } + end + end + end +end diff --git a/spec/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver_spec.rb b/spec/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver_spec.rb index b63eca4359d..6b5e351a610 100644 --- a/spec/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver_spec.rb +++ b/spec/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver_spec.rb @@ -31,16 +31,20 @@ RSpec.describe Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver do context 'as a non-admin user' do let(:current_user) { user } - it 'raises ResourceNotAvailable error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates a ResourceNotAvailable error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end context 'as an unauthenticated user' do let(:current_user) { nil } - it 'raises ResourceNotAvailable error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates a ResourceNotAvailable error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end diff --git a/spec/graphql/resolvers/base_resolver_spec.rb b/spec/graphql/resolvers/base_resolver_spec.rb index d77a0b6242e..39b00c14161 100644 --- a/spec/graphql/resolvers/base_resolver_spec.rb +++ b/spec/graphql/resolvers/base_resolver_spec.rb @@ -239,16 +239,16 @@ RSpec.describe Resolvers::BaseResolver do it 'increases complexity based on arguments' do field = Types::BaseField.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: described_class, null: false, max_page_size: 1) - expect(field.to_graphql.complexity.call({}, { sort: 'foo' }, 1)).to eq 3 - expect(field.to_graphql.complexity.call({}, { search: 'foo' }, 1)).to eq 7 + expect(field.complexity.call({}, { sort: 'foo' }, 1)).to eq 3 + expect(field.complexity.call({}, { search: 'foo' }, 1)).to eq 7 end it 'does not increase complexity when filtering by iids' do field = Types::BaseField.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: described_class, null: false, max_page_size: 100) - expect(field.to_graphql.complexity.call({}, { sort: 'foo' }, 1)).to eq 6 - expect(field.to_graphql.complexity.call({}, { sort: 'foo', iid: 1 }, 1)).to eq 3 - expect(field.to_graphql.complexity.call({}, { sort: 'foo', iids: [1, 2, 3] }, 1)).to eq 3 + expect(field.complexity.call({}, { sort: 'foo' }, 1)).to eq 6 + expect(field.complexity.call({}, { sort: 'foo', iid: 1 }, 1)).to eq 3 + expect(field.complexity.call({}, { sort: 'foo', iids: [1, 2, 3] }, 1)).to eq 3 end end diff --git a/spec/graphql/resolvers/blobs_resolver_spec.rb b/spec/graphql/resolvers/blobs_resolver_spec.rb index bc0344796ee..4b75351147c 100644 --- a/spec/graphql/resolvers/blobs_resolver_spec.rb +++ b/spec/graphql/resolvers/blobs_resolver_spec.rb @@ -26,8 +26,10 @@ RSpec.describe Resolvers::BlobsResolver do subject(:resolve_blobs) { resolve(described_class, obj: repository, args: args, ctx: { current_user: user }) } context 'when unauthorized' do - it 'raises an exception' do - expect { resolve_blobs }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + resolve_blobs + end end end @@ -68,6 +70,28 @@ RSpec.describe Resolvers::BlobsResolver do ) end end + + context 'when specifying an invalid ref' do + let(:ref) { 'ma:in' } + + it 'raises an ArgumentError' do + expect { resolve_blobs }.to raise_error( + Gitlab::Graphql::Errors::ArgumentError, + 'Ref is not valid' + ) + end + end + + context 'when passing an empty ref' do + let(:ref) { '' } + + it 'raises an ArgumentError' do + expect { resolve_blobs }.to raise_error( + Gitlab::Graphql::Errors::ArgumentError, + 'Ref is not valid' + ) + end + end end end end diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb index 6907c55bd48..392385d2a30 100644 --- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb +++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb @@ -25,10 +25,10 @@ RSpec.describe Resolvers::BoardListIssuesResolver do let(:wildcard_started) { 'STARTED' } let(:filters) { { milestone_title: ["started"], milestone_wildcard_id: wildcard_started } } - it 'raises a mutually exclusive filter error when milestone wildcard and title are provided' do - expect do + it 'generates a mutually exclusive filter error when milestone wildcard and title are provided' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do resolve_board_list_issues(args: { filters: filters }) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end end it 'returns the issues in the correct order' do @@ -63,10 +63,10 @@ RSpec.describe Resolvers::BoardListIssuesResolver do expect(result).to contain_exactly(incident) end - it 'raises an exception if both assignee_username and assignee_wildcard_id are present' do - expect do + it 'generates an error if both assignee_username and assignee_wildcard_id are present' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do resolve_board_list_issues(args: { filters: { assignee_username: ['username'], assignee_wildcard_id: 'NONE' } }) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end end it 'accepts assignee wildcard id NONE' do diff --git a/spec/graphql/resolvers/board_lists_resolver_spec.rb b/spec/graphql/resolvers/board_lists_resolver_spec.rb index fdcebd30bb3..7a1d8590546 100644 --- a/spec/graphql/resolvers/board_lists_resolver_spec.rb +++ b/spec/graphql/resolvers/board_lists_resolver_spec.rb @@ -74,9 +74,10 @@ RSpec.describe Resolvers::BoardListsResolver do expect(list).to eq List.none end - it 'raises an argument error if list ID is not valid' do - expect { resolve_board_lists(args: { id: 'test' }) } - .to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an error if list ID is not valid' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + resolve_board_lists(args: { id: 'test' }) + end end end end diff --git a/spec/graphql/resolvers/board_resolver_spec.rb b/spec/graphql/resolvers/board_resolver_spec.rb index e9c51a536ee..51a13850366 100644 --- a/spec/graphql/resolvers/board_resolver_spec.rb +++ b/spec/graphql/resolvers/board_resolver_spec.rb @@ -23,9 +23,9 @@ RSpec.describe Resolvers::BoardResolver do end it 'requires an ID' do - expect do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do resolve(described_class, obj: board_parent, args: {}, ctx: { current_user: user }) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end end context 'when querying for a single board' do diff --git a/spec/graphql/resolvers/ci/config_resolver_spec.rb b/spec/graphql/resolvers/ci/config_resolver_spec.rb index 97eee749290..3ff6d8f4347 100644 --- a/spec/graphql/resolvers/ci/config_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/config_resolver_spec.rb @@ -6,16 +6,24 @@ RSpec.describe Resolvers::Ci::ConfigResolver do include GraphqlHelpers describe '#resolve' do - before do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository, creator: user, namespace: user.namespace) } + let_it_be(:sha) { nil } + + let_it_be(:content) do + File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_includes.yml')) + end + + let(:ci_lint) do ci_lint_double = instance_double(::Gitlab::Ci::Lint) allow(ci_lint_double).to receive(:validate).and_return(fake_result) - allow(::Gitlab::Ci::Lint).to receive(:new).and_return(ci_lint_double) + ci_lint_double end - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :repository, creator: user, namespace: user.namespace) } - let_it_be(:sha) { nil } + before do + allow(::Gitlab::Ci::Lint).to receive(:new).and_return(ci_lint) + end subject(:response) do resolve(described_class, @@ -33,10 +41,6 @@ RSpec.describe Resolvers::Ci::ConfigResolver do ) end - let_it_be(:content) do - File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_includes.yml')) - end - it 'lints the ci config file and returns the merged yaml file' do expect(response[:status]).to eq(:valid) expect(response[:merged_yaml]).to eq(content) @@ -74,5 +78,23 @@ RSpec.describe Resolvers::Ci::ConfigResolver do expect(response[:errors]).to eq(['Invalid configuration format']) end end + + context 'with an invalid SHA' do + let_it_be(:sha) { ':' } + + let(:ci_lint) do + ci_lint_double = instance_double(::Gitlab::Ci::Lint) + allow(ci_lint_double).to receive(:validate).and_raise(GRPC::InvalidArgument) + + ci_lint_double + end + + it 'logs the invalid SHA to Sentry' do + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_exception) + .with(GRPC::InvalidArgument, sha: ':') + + response + end + end end end diff --git a/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb b/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb index 8522542498d..59616815de0 100644 --- a/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb @@ -54,10 +54,8 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do project.add_user(current_user, :developer) end - it 'raises error' do - expect do - resolve_scope - end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) { resolve_scope } end end end diff --git a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb index 9fe4c78f551..4c4aa4f53e1 100644 --- a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb +++ b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb @@ -15,7 +15,7 @@ RSpec.describe ResolvesPipelines do end end - let(:current_user) { create(:user) } + let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project, :private) } let_it_be(:pipeline) { create(:ci_pipeline, project: project) } @@ -23,13 +23,15 @@ RSpec.describe ResolvesPipelines do let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) } let_it_be(:ref_pipeline) { create(:ci_pipeline, project: project, ref: 'awesome-feature') } let_it_be(:sha_pipeline) { create(:ci_pipeline, project: project, sha: 'deadbeef') } + let_it_be(:username_pipeline) { create(:ci_pipeline, project: project, user: current_user) } let_it_be(:all_pipelines) do [ pipeline, failed_pipeline, success_pipeline, ref_pipeline, - sha_pipeline + sha_pipeline, + username_pipeline ] end @@ -37,7 +39,7 @@ RSpec.describe ResolvesPipelines do project.add_developer(current_user) end - it { is_expected.to have_graphql_arguments(:status, :scope, :ref, :sha, :source) } + it { is_expected.to have_graphql_arguments(:status, :scope, :ref, :sha, :source, :updated_after, :updated_before, :username) } it 'finds all pipelines' do expect(resolve_pipelines).to contain_exactly(*all_pipelines) @@ -71,6 +73,32 @@ RSpec.describe ResolvesPipelines do end end + it 'allows filtering by username' do + expect(resolve_pipelines(username: current_user.username)).to contain_exactly(username_pipeline) + end + + context 'filtering by updated_at' do + let_it_be(:old_pipeline) { create(:ci_pipeline, project: project, updated_at: 2.days.ago) } + let_it_be(:older_pipeline) { create(:ci_pipeline, project: project, updated_at: 5.days.ago) } + + it 'filters by updated_after' do + expect(resolve_pipelines(updated_after: 3.days.ago)).to contain_exactly(old_pipeline, *all_pipelines) + end + + it 'filters by updated_before' do + expect(resolve_pipelines(updated_before: 3.days.ago)).to contain_exactly(older_pipeline) + end + + it 'filters by both updated_after and updated_before with valid date range' do + expect(resolve_pipelines(updated_after: 10.days.ago, updated_before: 3.days.ago)).to contain_exactly(older_pipeline) + end + + it 'filters by both updated_after and updated_before with invalid date range' do + # updated_after is before updated_before so result set is empty - impossible + expect(resolve_pipelines(updated_after: 3.days.ago, updated_before: 10.days.ago)).to be_empty + end + end + it 'does not return any pipelines if the user does not have access' do expect(resolve_pipelines({}, {})).to be_empty end @@ -78,9 +106,9 @@ RSpec.describe ResolvesPipelines do it 'increases field complexity based on arguments' do field = Types::BaseField.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, null: false, max_page_size: 1) - expect(field.to_graphql.complexity.call({}, {}, 1)).to eq 2 - expect(field.to_graphql.complexity.call({}, { sha: 'foo' }, 1)).to eq 4 - expect(field.to_graphql.complexity.call({}, { sha: 'ref' }, 1)).to eq 4 + expect(field.complexity.call({}, {}, 1)).to eq 2 + expect(field.complexity.call({}, { sha: 'foo' }, 1)).to eq 4 + expect(field.complexity.call({}, { sha: 'ref' }, 1)).to eq 4 end def resolve_pipelines(args = {}, context = { current_user: current_user }) diff --git a/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb b/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb index 4bdef49499c..a16e8821cb5 100644 --- a/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb @@ -29,8 +29,10 @@ RSpec.describe Resolvers::DesignManagement::DesignAtVersionResolver do context 'when the user cannot see designs' do let(:current_user) { create(:user) } - it 'raises ResourceNotAvailable' do - expect { resolve_design }.to raise_error(resource_not_available) + it 'generates ResourceNotAvailable' do + expect_graphql_error_to_be_created(resource_not_available) do + resolve_design + end end end @@ -45,8 +47,10 @@ RSpec.describe Resolvers::DesignManagement::DesignAtVersionResolver do let(:global_id) { global_id_of(other_dav) } - it 'raises ResourceNotAvailable' do - expect { resolve_design }.to raise_error(resource_not_available) + it 'generates ResourceNotAvailable' do + expect_graphql_error_to_be_created(resource_not_available) do + resolve_design + end end context 'the current object does not constrain the issue' do diff --git a/spec/graphql/resolvers/design_management/design_resolver_spec.rb b/spec/graphql/resolvers/design_management/design_resolver_spec.rb index e33eaedf167..4c8b3116875 100644 --- a/spec/graphql/resolvers/design_management/design_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/design_resolver_spec.rb @@ -42,16 +42,20 @@ RSpec.describe Resolvers::DesignManagement::DesignResolver do context 'when no argument has been passed' do let(:args) { {} } - it 'raises an error' do - expect { resolve_design }.to raise_error(::Gitlab::Graphql::Errors::ArgumentError, /must/) + it 'generates an error' do + expect_graphql_error_to_be_created(::Gitlab::Graphql::Errors::ArgumentError, /must/) do + resolve_design + end end end context 'when both arguments have been passed' do let(:args) { { filename: first_design.filename, id: GitlabSchema.id_from_object(first_design).to_s } } - it 'raises an error' do - expect { resolve_design }.to raise_error(::Gitlab::Graphql::Errors::ArgumentError, /may/) + it 'generates an error' do + expect_graphql_error_to_be_created(::Gitlab::Graphql::Errors::ArgumentError, /may/) do + resolve_design + end end end diff --git a/spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb b/spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb index cc7e2f6814a..829227185c2 100644 --- a/spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb @@ -24,8 +24,10 @@ RSpec.describe Resolvers::DesignManagement::Version::DesignAtVersionResolver do shared_examples 'a bad argument' do let(:err_class) { ::Gitlab::Graphql::Errors::ArgumentError } - it 'raises an appropriate error' do - expect { resolve_objects }.to raise_error(err_class) + it 'generates an error' do + expect_graphql_error_to_be_created(err_class) do + resolve_objects + end end end diff --git a/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb index b0fc78af2af..8b9874c3580 100644 --- a/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb @@ -26,8 +26,10 @@ RSpec.describe Resolvers::DesignManagement::VersionInCollectionResolver do subject(:result) { resolve_version(issue.design_collection) } context 'Neither id nor sha is passed as parameters' do - it 'raises an appropriate error' do - expect { result }.to raise_error(appropriate_error) + it 'generates an appropriate error' do + expect_graphql_error_to_be_created(appropriate_error) do + result + end end end diff --git a/spec/graphql/resolvers/design_management/version_resolver_spec.rb b/spec/graphql/resolvers/design_management/version_resolver_spec.rb index af1e6a73d09..ab1d7d4d9c5 100644 --- a/spec/graphql/resolvers/design_management/version_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/version_resolver_spec.rb @@ -22,8 +22,10 @@ RSpec.describe Resolvers::DesignManagement::VersionResolver do context 'the current user is not authorized' do let(:current_user) { create(:user) } - it 'raises an error on resolution' do - expect { resolve_version }.to raise_error(::Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error on resolution' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + resolve_version + end end end diff --git a/spec/graphql/resolvers/design_management/versions_resolver_spec.rb b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb index 2c9c3a47650..d98138f6385 100644 --- a/spec/graphql/resolvers/design_management/versions_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb @@ -98,8 +98,10 @@ RSpec.describe Resolvers::DesignManagement::VersionsResolver do } end - it 'raises a suitable error' do - expect { result }.to raise_error(GraphQL::ExecutionError) + it 'generates a suitable error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + result + end end end end diff --git a/spec/graphql/resolvers/environments_resolver_spec.rb b/spec/graphql/resolvers/environments_resolver_spec.rb index 6c999e5d0e7..9f4c4716de0 100644 --- a/spec/graphql/resolvers/environments_resolver_spec.rb +++ b/spec/graphql/resolvers/environments_resolver_spec.rb @@ -46,10 +46,10 @@ RSpec.describe Resolvers::EnvironmentsResolver do expect(resolve_environments(states: ['available'])).to contain_exactly(environment1, environment3) end - it 'returns error if requested state is invalid' do - expect { resolve_environments(states: ['invalid']) }.to( - raise_error(Gitlab::Graphql::Errors::ArgumentError) - ) + it 'generates an error if requested state is invalid' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + resolve_environments(states: ['invalid']) + end end end diff --git a/spec/graphql/resolvers/group_issues_resolver_spec.rb b/spec/graphql/resolvers/group_issues_resolver_spec.rb index e17429560ac..f5f6086cc09 100644 --- a/spec/graphql/resolvers/group_issues_resolver_spec.rb +++ b/spec/graphql/resolvers/group_issues_resolver_spec.rb @@ -86,10 +86,10 @@ RSpec.describe Resolvers::GroupIssuesResolver do end context 'release_tag filter' do - it 'returns an error when trying to filter by negated release_tag' do - expect do + it 'generates an error when trying to filter by negated release_tag' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.') do resolve_issues(not: { release_tag: ['v1.0'] }) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.') + end end end end diff --git a/spec/graphql/resolvers/group_labels_resolver_spec.rb b/spec/graphql/resolvers/group_labels_resolver_spec.rb index 3f4ad8760c0..2031e534703 100644 --- a/spec/graphql/resolvers/group_labels_resolver_spec.rb +++ b/spec/graphql/resolvers/group_labels_resolver_spec.rb @@ -27,8 +27,10 @@ RSpec.describe Resolvers::GroupLabelsResolver do describe '#resolve' do context 'with unauthorized user' do - it 'raises error' do - expect { resolve_labels(subgroup) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + resolve_labels(subgroup) + end end end diff --git a/spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb b/spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb new file mode 100644 index 00000000000..fcf67120b0e --- /dev/null +++ b/spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::GroupMembers::NotificationEmailResolver do + include GraphqlHelpers + + describe '#resolve' do + let_it_be(:group) { create(:group) } + let_it_be(:developer) { create(:user) } + + before do + group.add_developer(developer) + end + + specify do + expect(described_class).to have_nullable_graphql_type(GraphQL::Types::String) + end + + subject { batch_sync { resolve_notification_email(developer.group_members.first, current_user) }} + + context 'when current_user is admin' do + let(:current_user) { create(:user, :admin) } + + before do + allow(current_user).to receive(:can_admin_all_resources?).and_return(true) + end + + it 'returns email' do + expect(subject).to eq(developer.email) + end + end + + context 'when current_user is not admin' do + let(:current_user) { create(:user) } + + it 'raises ResourceNotAvailable error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end + end + end + + def resolve_notification_email(obj, user) + resolve(described_class, obj: obj, ctx: { current_user: user }) + end +end diff --git a/spec/graphql/resolvers/group_milestones_resolver_spec.rb b/spec/graphql/resolvers/group_milestones_resolver_spec.rb index acfc8313407..7abc779a63c 100644 --- a/spec/graphql/resolvers/group_milestones_resolver_spec.rb +++ b/spec/graphql/resolvers/group_milestones_resolver_spec.rb @@ -101,38 +101,38 @@ RSpec.describe Resolvers::GroupMilestonesResolver do context 'by timeframe' do context 'when start_date and end_date are present' do context 'when start date is after end_date' do - it 'raises error' do - expect do + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate") do resolve_group_milestones(start_date: now, end_date: now - 2.days) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate") + end end end end context 'when only start_date is present' do - it 'raises error' do - expect do + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do resolve_group_milestones(start_date: now) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) + end end end context 'when only end_date is present' do - it 'raises error' do - expect do + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do resolve_group_milestones(end_date: now) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) + end end end end context 'when user cannot read milestones' do - it 'raises error' do + it 'generates an error' do unauthorized_user = create(:user) - expect do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do resolve_group_milestones({}, { current_user: unauthorized_user }) - end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end end end diff --git a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb index 3fbd9bd2368..77f4ce4cac5 100644 --- a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb +++ b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb @@ -70,10 +70,10 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do end context 'when both assignee_username and assignee_usernames are provided' do - it 'raises a mutually exclusive filter error' do - expect do + it 'generates a mutually exclusive filter error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.') do resolve_issue_status_counts(assignee_usernames: [current_user.username], assignee_username: current_user.username) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.') + end end end diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb index dc717b113c1..5e9a3d0a68b 100644 --- a/spec/graphql/resolvers/issues_resolver_spec.rb +++ b/spec/graphql/resolvers/issues_resolver_spec.rb @@ -78,10 +78,10 @@ RSpec.describe Resolvers::IssuesResolver do expect(resolve_issues(milestone_wildcard_id: wildcard_none)).to contain_exactly(issue2) end - it 'raises a mutually exclusive filter error when wildcard and title are provided' do - expect do + it 'generates a mutually exclusive filter error when wildcard and title are provided' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.') do resolve_issues(milestone_title: ["started milestone"], milestone_wildcard_id: wildcard_started) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.') + end end context 'negated filtering' do @@ -97,10 +97,10 @@ RSpec.describe Resolvers::IssuesResolver do expect(resolve_issues(not: { milestone_wildcard_id: wildcard_upcoming })).to contain_exactly(issue6) end - it 'raises a mutually exclusive filter error when wildcard and title are provided as negated filters' do - expect do + it 'generates a mutually exclusive filter error when wildcard and title are provided as negated filters' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.') do resolve_issues(not: { milestone_title: ["started milestone"], milestone_wildcard_id: wildcard_started }) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.') + end end end end @@ -122,10 +122,10 @@ RSpec.describe Resolvers::IssuesResolver do end context 'when release_tag_wildcard_id is also provided' do - it 'raises a mutually eclusive argument error' do - expect do + it 'generates a mutually eclusive argument error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [releaseTag, releaseTagWildcardId] arguments is allowed at the same time.') do resolve_issues(release_tag: [release1.tag], release_tag_wildcard_id: 'ANY') - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [releaseTag, releaseTagWildcardId] arguments is allowed at the same time.') + end end end end @@ -191,10 +191,10 @@ RSpec.describe Resolvers::IssuesResolver do end context 'when both assignee_username and assignee_usernames are provided' do - it 'raises a mutually exclusive filter error' do - expect do + it 'generates a mutually exclusive filter error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.') do resolve_issues(assignee_usernames: [assignee.username], assignee_username: assignee.username) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.') + end end end end @@ -331,11 +331,12 @@ RSpec.describe Resolvers::IssuesResolver do stub_feature_flags(disable_anonymous_search: true) end - it 'returns an error' do + it 'generates an error' do error_message = "User must be authenticated to include the `search` argument." - expect { resolve(described_class, obj: public_project, args: { search: 'test' }, ctx: { current_user: nil }) } - .to raise_error(Gitlab::Graphql::Errors::ArgumentError, error_message) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, error_message) do + resolve(described_class, obj: public_project, args: { search: 'test' }, ctx: { current_user: nil }) + end end end @@ -618,8 +619,8 @@ RSpec.describe Resolvers::IssuesResolver do it 'increases field complexity based on arguments' do field = Types::BaseField.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: described_class, null: false, max_page_size: 100) - expect(field.to_graphql.complexity.call({}, {}, 1)).to eq 4 - expect(field.to_graphql.complexity.call({}, { labelName: 'foo' }, 1)).to eq 8 + expect(field.complexity.call({}, {}, 1)).to eq 4 + expect(field.complexity.call({}, { labelName: 'foo' }, 1)).to eq 8 end def create_issue_with_severity(project, severity:) diff --git a/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb b/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb index bdb1ced46ae..e4cf62b0361 100644 --- a/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb +++ b/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb @@ -34,8 +34,10 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do allow(kas_client).to receive(:list_agent_config_files).and_raise(GRPC::DeadlineExceeded) end - it 'raises a graphql error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, 'GRPC::DeadlineExceeded') + it 'generates a graphql error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable, 'GRPC::DeadlineExceeded') do + subject + end end end diff --git a/spec/graphql/resolvers/labels_resolver_spec.rb b/spec/graphql/resolvers/labels_resolver_spec.rb index be6229553d7..efd2596b9eb 100644 --- a/spec/graphql/resolvers/labels_resolver_spec.rb +++ b/spec/graphql/resolvers/labels_resolver_spec.rb @@ -28,7 +28,9 @@ RSpec.describe Resolvers::LabelsResolver do describe '#resolve' do context 'with unauthorized user' do it 'returns no labels' do - expect { resolve_labels(project) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + resolve_labels(project) + end end end diff --git a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb index b1f50a4a4a5..eb4d0ab6f37 100644 --- a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb +++ b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb @@ -147,8 +147,8 @@ RSpec.describe Resolvers::NamespaceProjectsResolver do it 'has an high complexity regardless of arguments' do field = Types::BaseField.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: described_class, null: false, max_page_size: 100) - expect(field.to_graphql.complexity.call({}, {}, 1)).to eq 24 - expect(field.to_graphql.complexity.call({}, { include_subgroups: true }, 1)).to eq 24 + expect(field.complexity.call({}, {}, 1)).to eq 24 + expect(field.complexity.call({}, { include_subgroups: true }, 1)).to eq 24 end def resolve_projects(args = { include_subgroups: false, sort: nil, search: nil, ids: nil }, context = { current_user: current_user }) diff --git a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb index 892dc641201..c757c876616 100644 --- a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb +++ b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb @@ -25,32 +25,40 @@ RSpec.describe Resolvers::PackagePipelinesResolver do context 'with invalid after' do let(:args) { { first: 1, after: 'not_json_string' } } - it 'raises argument error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an argument error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + subject + end end end context 'with invalid after key' do let(:args) { { first: 1, after: encode_cursor(foo: 3) } } - it 'raises argument error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an argument error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + subject + end end end context 'with invalid before' do let(:args) { { last: 1, before: 'not_json_string' } } - it 'raises argument error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an argument error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + subject + end end end context 'with invalid before key' do let(:args) { { last: 1, before: encode_cursor(foo: 3) } } - it 'raises argument error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an argument error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + subject + end end end diff --git a/spec/graphql/resolvers/paginated_tree_resolver_spec.rb b/spec/graphql/resolvers/paginated_tree_resolver_spec.rb index 82b05937aa3..4b05e9076d7 100644 --- a/spec/graphql/resolvers/paginated_tree_resolver_spec.rb +++ b/spec/graphql/resolvers/paginated_tree_resolver_spec.rb @@ -65,7 +65,11 @@ RSpec.describe Resolvers::PaginatedTreeResolver do context 'when cursor is invalid' do let(:args) { super().merge(after: 'invalid') } - it { expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) } + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + subject + end + end end it 'returns all tree entries during cursor pagination' do diff --git a/spec/graphql/resolvers/project_milestones_resolver_spec.rb b/spec/graphql/resolvers/project_milestones_resolver_spec.rb index e168291c804..2cf490c2b6a 100644 --- a/spec/graphql/resolvers/project_milestones_resolver_spec.rb +++ b/spec/graphql/resolvers/project_milestones_resolver_spec.rb @@ -103,27 +103,27 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do end context 'when start date is after end_date' do - it 'raises error' do - expect do + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'startDate is after endDate') do resolve_project_milestones(start_date: Time.now, end_date: Time.now - 2.days) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate") + end end end end context 'when only start_date is present' do - it 'raises error' do - expect do + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do resolve_project_milestones(start_date: Time.now) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) + end end end context 'when only end_date is present' do - it 'raises error' do - expect do + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do resolve_project_milestones(end_date: Time.now) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) + end end end @@ -174,12 +174,12 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do end context 'when user cannot read milestones' do - it 'raises error' do + it 'generates an error' do unauthorized_user = create(:user) - expect do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do resolve_project_milestones({}, { current_user: unauthorized_user }) - end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end end end end diff --git a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb index 6a8aa39f3b2..398f8f52269 100644 --- a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb +++ b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb @@ -85,13 +85,15 @@ RSpec.describe Resolvers::ProjectPipelineResolver do end it 'errors when no iid or sha is passed' do - expect { resolve_pipeline(project, {}) } - .to raise_error(Gitlab::Graphql::Errors::ArgumentError) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + resolve_pipeline(project, {}) + end end it 'errors when both iid and sha are passed' do - expect { resolve_pipeline(project, { iid: '1234', sha: 'sha' }) } - .to raise_error(Gitlab::Graphql::Errors::ArgumentError) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + resolve_pipeline(project, { iid: '1234', sha: 'sha' }) + end end context 'when the pipeline is a dangling pipeline' do diff --git a/spec/graphql/resolvers/project_resolver_spec.rb b/spec/graphql/resolvers/project_resolver_spec.rb index cd3fdc788e6..dec9d4701e1 100644 --- a/spec/graphql/resolvers/project_resolver_spec.rb +++ b/spec/graphql/resolvers/project_resolver_spec.rb @@ -36,8 +36,8 @@ RSpec.describe Resolvers::ProjectResolver do field1 = Types::BaseField.new(name: 'test', type: GraphQL::Types::String, resolver_class: described_class, null: false, max_page_size: 100) field2 = Types::BaseField.new(name: 'test', type: GraphQL::Types::String, resolver_class: described_class, null: false, max_page_size: 1) - expect(field1.to_graphql.complexity.call({}, {}, 1)).to eq 2 - expect(field2.to_graphql.complexity.call({}, {}, 1)).to eq 2 + expect(field1.complexity.call({}, {}, 1)).to eq 2 + expect(field2.complexity.call({}, {}, 1)).to eq 2 end def resolve_project(full_path) diff --git a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb index c6d8c518fb7..b95bab41e3e 100644 --- a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb +++ b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb @@ -14,10 +14,10 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do let_it_be(:project) { create(:project) } shared_examples 'no project service access' do - it 'raises error' do - expect do + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do resolve_jira_projects - end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end end end @@ -89,11 +89,14 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do .to_raise(JIRA::HTTPError.new(double(message: '{"errorMessages":["Some failure"]}'))) end - it 'raises failure error' do + it 'generates a failure error' do config_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira/configure') docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: config_docs_link_url } error_message = 'An error occurred while requesting data from Jira: Some failure. Check your %{docs_link_start}Jira integration configuration</a> and try again.' % { docs_link_start: docs_link_start } - expect { resolve_jira_projects }.to raise_error(error_message) + + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::BaseError, error_message) do + resolve_jira_projects + end end end end diff --git a/spec/graphql/resolvers/projects/snippets_resolver_spec.rb b/spec/graphql/resolvers/projects/snippets_resolver_spec.rb index 2d8929c0e8f..b963f2509db 100644 --- a/spec/graphql/resolvers/projects/snippets_resolver_spec.rb +++ b/spec/graphql/resolvers/projects/snippets_resolver_spec.rb @@ -81,12 +81,14 @@ RSpec.describe Resolvers::Projects::SnippetsResolver do end context 'when project snippets are disabled' do - it 'raises an error' do + it 'generates an error' do disabled_snippet_project = create(:project, :snippets_disabled) disabled_snippet_project.add_developer(current_user) expect(SnippetsFinder).not_to receive(:new) - expect { resolve_snippets(obj: disabled_snippet_project) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + resolve_snippets(obj: disabled_snippet_project) + end end end end diff --git a/spec/graphql/resolvers/snippets_resolver_spec.rb b/spec/graphql/resolvers/snippets_resolver_spec.rb index 11cb1c0ec4b..f9feb8901cd 100644 --- a/spec/graphql/resolvers/snippets_resolver_spec.rb +++ b/spec/graphql/resolvers/snippets_resolver_spec.rb @@ -108,15 +108,15 @@ RSpec.describe Resolvers::SnippetsResolver do end.to raise_error(GraphQL::CoercionError, '"foo" is not a valid Global ID') end - it 'returns an error if both project and author are provided' do - expect do + it 'generates an error if both project and author are provided' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do args = { author_id: current_user.to_global_id, project_id: project.to_global_id } resolve_snippets(args: args) - end.to raise_error(Gitlab::Graphql::Errors::ArgumentError) + end end end end diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb index 9b3f555071e..84fa2932829 100644 --- a/spec/graphql/resolvers/timelog_resolver_spec.rb +++ b/spec/graphql/resolvers/timelog_resolver_spec.rb @@ -85,27 +85,30 @@ RSpec.describe Resolvers::TimelogResolver do context 'when start_time and start_date are present' do let(:args) { { start_time: 6.days.ago, start_date: 6.days.ago } } - it 'returns correct error' do - expect { timelogs } - .to raise_error(error_class, /Provide either a start date or time, but not both/) + it 'generates an error' do + expect_graphql_error_to_be_created(error_class, /Provide either a start date or time, but not both/) do + timelogs + end end end context 'when end_time and end_date are present' do let(:args) { { end_time: 2.days.ago, end_date: 2.days.ago } } - it 'returns correct error' do - expect { timelogs } - .to raise_error(error_class, /Provide either an end date or time, but not both/) + it 'generates an error' do + expect_graphql_error_to_be_created(error_class, /Provide either an end date or time, but not both/) do + timelogs + end end end context 'when start argument is after end argument' do let(:args) { { start_time: 2.days.ago, end_time: 6.days.ago } } - it 'returns correct error' do - expect { timelogs } - .to raise_error(error_class, /Start argument must be before End argument/) + it 'generates an error' do + expect_graphql_error_to_be_created(error_class, /Start argument must be before End argument/) do + timelogs + end end end end @@ -170,27 +173,30 @@ RSpec.describe Resolvers::TimelogResolver do context 'when start_time and start_date are present' do let(:args) { { start_time: short_time_ago, start_date: short_time_ago } } - it 'returns correct error' do - expect { timelogs } - .to raise_error(error_class, /Provide either a start date or time, but not both/) + it 'generates an error' do + expect_graphql_error_to_be_created(error_class, /Provide either a start date or time, but not both/) do + timelogs + end end end context 'when end_time and end_date are present' do let(:args) { { end_time: short_time_ago, end_date: short_time_ago } } - it 'returns correct error' do - expect { timelogs } - .to raise_error(error_class, /Provide either an end date or time, but not both/) + it 'generates an error' do + expect_graphql_error_to_be_created(error_class, /Provide either an end date or time, but not both/) do + timelogs + end end end context 'when start argument is after end argument' do let(:args) { { start_time: short_time_ago, end_time: medium_time_ago } } - it 'returns correct error' do - expect { timelogs } - .to raise_error(error_class, /Start argument must be before End argument/) + it 'generates an error' do + expect_graphql_error_to_be_created(error_class, /Start argument must be before End argument/) do + timelogs + end end end end @@ -273,9 +279,10 @@ RSpec.describe Resolvers::TimelogResolver do let(:args) { {} } let(:extra_args) { {} } - it 'returns correct error' do - expect { timelogs } - .to raise_error(error_class, /Provide at least one argument/) + it 'generates an error' do + expect_graphql_error_to_be_created(error_class, /Provide at least one argument/) do + timelogs + end end end diff --git a/spec/graphql/resolvers/topics_resolver_spec.rb b/spec/graphql/resolvers/topics_resolver_spec.rb index 3ff1dabc927..89f4583bce8 100644 --- a/spec/graphql/resolvers/topics_resolver_spec.rb +++ b/spec/graphql/resolvers/topics_resolver_spec.rb @@ -6,9 +6,9 @@ RSpec.describe Resolvers::TopicsResolver do include GraphqlHelpers describe '#resolve' do - let!(:topic1) { create(:topic, name: 'GitLab', total_projects_count: 1) } - let!(:topic2) { create(:topic, name: 'git', total_projects_count: 2) } - let!(:topic3) { create(:topic, name: 'topic3', total_projects_count: 3) } + let!(:topic1) { create(:topic, name: 'GitLab', non_private_projects_count: 1) } + let!(:topic2) { create(:topic, name: 'git', non_private_projects_count: 2) } + let!(:topic3) { create(:topic, name: 'topic3', non_private_projects_count: 3) } it 'finds all topics' do expect(resolve_topics).to eq([topic3, topic2, topic1]) diff --git a/spec/graphql/resolvers/user_discussions_count_resolver_spec.rb b/spec/graphql/resolvers/user_discussions_count_resolver_spec.rb index 70f06b58a65..ef70418ab4b 100644 --- a/spec/graphql/resolvers/user_discussions_count_resolver_spec.rb +++ b/spec/graphql/resolvers/user_discussions_count_resolver_spec.rb @@ -43,7 +43,9 @@ RSpec.describe Resolvers::UserDiscussionsCountResolver do subject { batch_sync { resolve_user_discussions_count(private_issue) } } it 'returns no discussions' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end end diff --git a/spec/graphql/resolvers/user_notes_count_resolver_spec.rb b/spec/graphql/resolvers/user_notes_count_resolver_spec.rb index bc173b2a166..b3368d532b2 100644 --- a/spec/graphql/resolvers/user_notes_count_resolver_spec.rb +++ b/spec/graphql/resolvers/user_notes_count_resolver_spec.rb @@ -44,8 +44,10 @@ RSpec.describe Resolvers::UserNotesCountResolver do context 'when a user does not have permission to view notes' do subject { batch_sync { resolve_user_notes_count(private_issue) } } - it 'raises an error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end end @@ -80,8 +82,10 @@ RSpec.describe Resolvers::UserNotesCountResolver do context 'when a user does not have permission to view notes' do subject { batch_sync { resolve_user_notes_count(private_merge_request) } } - it 'raises an error' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + subject + end end end end diff --git a/spec/graphql/resolvers/user_resolver_spec.rb b/spec/graphql/resolvers/user_resolver_spec.rb index 3ee9f63d832..446d765d3ee 100644 --- a/spec/graphql/resolvers/user_resolver_spec.rb +++ b/spec/graphql/resolvers/user_resolver_spec.rb @@ -9,15 +9,17 @@ RSpec.describe Resolvers::UserResolver do let_it_be(:user) { create(:user) } context 'when neither an ID or a username is provided' do - it 'raises an ArgumentError' do - expect { resolve_user } - .to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an ArgumentError' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + resolve_user + end end end - it 'raises an ArgumentError when both an ID and username are provided' do - expect { resolve_user(id: user.to_global_id, username: user.username) } - .to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an ArgumentError when both an ID and username are provided' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + resolve_user(id: user.to_global_id, username: user.username) + end end context 'by username' do diff --git a/spec/graphql/resolvers/users_resolver_spec.rb b/spec/graphql/resolvers/users_resolver_spec.rb index 29947c33430..b01cc0d43e3 100644 --- a/spec/graphql/resolvers/users_resolver_spec.rb +++ b/spec/graphql/resolvers/users_resolver_spec.rb @@ -14,10 +14,12 @@ RSpec.describe Resolvers::UsersResolver do end describe '#resolve' do - it 'raises an error when read_users_list is not authorized' do + it 'generates an error when read_users_list is not authorized' do expect(Ability).to receive(:allowed?).with(current_user, :read_users_list).and_return(false) - expect { resolve_users }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do + resolve_users + end end context 'when no arguments are passed' do @@ -27,9 +29,10 @@ RSpec.describe Resolvers::UsersResolver do end context 'when both ids and usernames are passed ' do - it 'raises an error' do - expect { resolve_users( args: { ids: [user1.to_global_id.to_s], usernames: [user1.username] } ) } - .to raise_error(Gitlab::Graphql::Errors::ArgumentError) + it 'generates an error' do + expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do + resolve_users( args: { ids: [user1.to_global_id.to_s], usernames: [user1.username] } ) + end end end diff --git a/spec/graphql/resolvers/work_item_resolver_spec.rb b/spec/graphql/resolvers/work_item_resolver_spec.rb new file mode 100644 index 00000000000..c7e2beecb51 --- /dev/null +++ b/spec/graphql/resolvers/work_item_resolver_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::WorkItemResolver do + include GraphqlHelpers + + describe '#resolve' do + let_it_be(:developer) { create(:user) } + let_it_be(:project) { create(:project, :private).tap { |project| project.add_developer(developer) } } + let_it_be(:work_item) { create(:work_item, project: project) } + + let(:current_user) { developer } + + subject(:resolved_work_item) { resolve_work_item('id' => work_item.to_gid.to_s) } + + context 'when the user can read the work item' do + it { is_expected.to eq(work_item) } + end + + context 'when the user can not read the work item' do + let(:current_user) { create(:user) } + + it 'raises a resource not available error' do + expect { resolved_work_item }.to raise_error(::Gitlab::Graphql::Errors::ResourceNotAvailable) + end + end + + context 'when the work_items feature flag is disabled' do + before do + stub_feature_flags(work_items: false) + end + + it { is_expected.to be_nil } + end + end + + private + + def resolve_work_item(args = {}) + resolve(described_class, args: args, ctx: { current_user: current_user }) + end +end diff --git a/spec/graphql/resolvers/work_items/types_resolver_spec.rb b/spec/graphql/resolvers/work_items/types_resolver_spec.rb index b85989256b5..f7aeed30fd3 100644 --- a/spec/graphql/resolvers/work_items/types_resolver_spec.rb +++ b/spec/graphql/resolvers/work_items/types_resolver_spec.rb @@ -7,16 +7,51 @@ RSpec.describe Resolvers::WorkItems::TypesResolver do let_it_be(:current_user) { create(:user) } let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } before_all do group.add_developer(current_user) end - describe '#resolve' do - it 'returns all default work item types' do - result = resolve(described_class, obj: group) + shared_examples 'a work item type resolver' do + let(:args) { {} } + + subject(:result) { resolve(described_class, obj: object, args: args) } + it 'returns all default work item types' do expect(result.to_a).to match(WorkItems::Type.default.order_by_name_asc) end + + context 'when requesting taskable types' do + let(:args) { { taskable: true } } + + it 'returns only taskable types' do + expect(result.to_a).to contain_exactly(WorkItems::Type.default_by_type(:task)) + end + end + + context 'when work_items feature flag is disabled' do + before do + stub_feature_flags(work_items: false) + end + + it 'returns nil' do + expect(result).to be_nil + end + end + end + + describe '#resolve' do + context 'when parent is a group' do + let(:object) { group } + + it_behaves_like 'a work item type resolver' + end + + context 'when parent is a project' do + let(:object) { project } + + it_behaves_like 'a work item type resolver' + end end end diff --git a/spec/graphql/types/alert_management/alert_type_spec.rb b/spec/graphql/types/alert_management/alert_type_spec.rb index 9ff01418c9a..69cbdb998eb 100644 --- a/spec/graphql/types/alert_management/alert_type_spec.rb +++ b/spec/graphql/types/alert_management/alert_type_spec.rb @@ -7,6 +7,8 @@ RSpec.describe GitlabSchema.types['AlertManagementAlert'] do specify { expect(described_class).to require_graphql_authorizations(:read_alert_management_alert) } + specify { expect(described_class.interfaces).to include(Types::TodoableInterface) } + it 'exposes the expected fields' do expected_fields = %i[ iid @@ -34,6 +36,7 @@ RSpec.describe GitlabSchema.types['AlertManagementAlert'] do details_url prometheus_alert environment + web_url ] expect(described_class).to have_graphql_fields(*expected_fields) diff --git a/spec/graphql/types/base_enum_spec.rb b/spec/graphql/types/base_enum_spec.rb index bab0278ee25..65a345052c7 100644 --- a/spec/graphql/types/base_enum_spec.rb +++ b/spec/graphql/types/base_enum_spec.rb @@ -102,9 +102,9 @@ RSpec.describe Types::BaseEnum do it 'sets the values defined by the declarative enum' do set_declarative_enum - expect(enum_type.values.keys).to eq(['FOO']) - expect(enum_type.values.values.map(&:description)).to eq(['description of foo']) - expect(enum_type.values.values.map(&:value)).to eq([0]) + expect(enum_type.values.keys).to contain_exactly('FOO') + expect(enum_type.values.values.map(&:description)).to contain_exactly('description of foo') + expect(enum_type.values.values.map(&:value)).to contain_exactly('foo') end end end @@ -136,7 +136,7 @@ RSpec.describe Types::BaseEnum do value 'TEST_VALUE', **args end - enum.to_graphql.values['TEST_VALUE'] + enum.values['TEST_VALUE'] end end end diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb index 31d07f701e8..9d02f061435 100644 --- a/spec/graphql/types/base_field_spec.rb +++ b/spec/graphql/types/base_field_spec.rb @@ -19,7 +19,7 @@ RSpec.describe Types::BaseField do it 'defaults to 1' do field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true) - expect(field.to_graphql.complexity).to eq 1 + expect(field.complexity).to eq 1 end describe '#base_complexity' do @@ -43,7 +43,7 @@ RSpec.describe Types::BaseField do it 'has specified value' do field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12) - expect(field.to_graphql.complexity).to eq 12 + expect(field.complexity).to eq 12 end context 'when field has a resolver' do @@ -51,7 +51,7 @@ RSpec.describe Types::BaseField do let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: resolver, complexity: 2, max_page_size: 100, null: true) } it 'uses this complexity' do - expect(field.to_graphql.complexity).to eq 2 + expect(field.complexity).to eq 2 end end @@ -59,13 +59,13 @@ RSpec.describe Types::BaseField do let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: resolver, max_page_size: 100, null: true) } it 'sets complexity depending on arguments for resolvers' do - expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 4 - expect(field.to_graphql.complexity.call({}, { first: 50 }, 2)).to eq 3 + expect(field.complexity.call({}, {}, 2)).to eq 4 + expect(field.complexity.call({}, { first: 50 }, 2)).to eq 3 end it 'sets complexity depending on number load limits for resolvers' do - expect(field.to_graphql.complexity.call({}, { first: 1 }, 2)).to eq 2 - expect(field.to_graphql.complexity.call({}, { first: 1, foo: true }, 2)).to eq 4 + expect(field.complexity.call({}, { first: 1 }, 2)).to eq 2 + expect(field.complexity.call({}, { first: 1, foo: true }, 2)).to eq 4 end end @@ -73,8 +73,8 @@ RSpec.describe Types::BaseField do it 'sets complexity as normal' do field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, max_page_size: 100, null: true) - expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 2 - expect(field.to_graphql.complexity.call({}, { first: 50 }, 2)).to eq 2 + expect(field.complexity.call({}, {}, 2)).to eq 2 + expect(field.complexity.call({}, { first: 50 }, 2)).to eq 2 end end end @@ -84,9 +84,9 @@ RSpec.describe Types::BaseField do it 'adds 1 if true' do with_gitaly_field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, null: true, calls_gitaly: true) without_gitaly_field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, null: true) - base_result = without_gitaly_field.to_graphql.complexity.call({}, {}, 2) + base_result = without_gitaly_field.complexity.call({}, {}, 2) - expect(with_gitaly_field.to_graphql.complexity.call({}, {}, 2)).to eq base_result + 1 + expect(with_gitaly_field.complexity.call({}, {}, 2)).to eq base_result + 1 end end @@ -94,7 +94,7 @@ RSpec.describe Types::BaseField do it 'adds 1 if true' do field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, calls_gitaly: true) - expect(field.to_graphql.complexity).to eq 2 + expect(field.complexity).to eq 2 end end @@ -108,14 +108,14 @@ RSpec.describe Types::BaseField do it 'has complexity set to that constant' do field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12) - expect(field.to_graphql.complexity).to eq 12 + expect(field.complexity).to eq 12 end it 'does not raise an error even with Gitaly calls' do allow(Gitlab::GitalyClient).to receive(:get_request_count).and_return([0, 1]) field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12) - expect(field.to_graphql.complexity).to eq 12 + expect(field.complexity).to eq 12 end end end diff --git a/spec/graphql/types/ci/runner_web_url_edge_spec.rb b/spec/graphql/types/ci/runner_web_url_edge_spec.rb new file mode 100644 index 00000000000..08718df0a5b --- /dev/null +++ b/spec/graphql/types/ci/runner_web_url_edge_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::Ci::RunnerWebUrlEdge do + specify { expect(described_class.graphql_name).to eq('RunnerWebUrlEdge') } + + it 'contains URL attributes' do + expected_fields = %w[edit_url web_url] + + expect(described_class).to include_graphql_fields(*expected_fields) + end +end diff --git a/spec/graphql/types/commit_type_spec.rb b/spec/graphql/types/commit_type_spec.rb index c1d838c3117..fe8df15028d 100644 --- a/spec/graphql/types/commit_type_spec.rb +++ b/spec/graphql/types/commit_type_spec.rb @@ -7,6 +7,8 @@ RSpec.describe GitlabSchema.types['Commit'] do specify { expect(described_class).to require_graphql_authorizations(:download_code) } + specify { expect(described_class).to include(Types::TodoableInterface) } + it 'contains attributes related to commit' do expect(described_class).to have_graphql_fields( :id, :sha, :short_id, :title, :full_title, :full_title_html, :description, :description_html, :message, :title_html, :authored_date, diff --git a/spec/graphql/types/container_repository_details_type_spec.rb b/spec/graphql/types/container_repository_details_type_spec.rb index 45f6449d8c8..aa770284f89 100644 --- a/spec/graphql/types/container_repository_details_type_spec.rb +++ b/spec/graphql/types/container_repository_details_type_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['ContainerRepositoryDetails'] do - fields = %i[id name path location created_at updated_at expiration_policy_started_at status tags_count can_delete expiration_policy_cleanup_status tags project] + fields = %i[id name path location created_at updated_at expiration_policy_started_at status tags_count can_delete expiration_policy_cleanup_status tags size project] it { expect(described_class.graphql_name).to eq('ContainerRepositoryDetails') } diff --git a/spec/graphql/types/design_management/design_type_spec.rb b/spec/graphql/types/design_management/design_type_spec.rb index cae98a013e1..9c460e9058a 100644 --- a/spec/graphql/types/design_management/design_type_spec.rb +++ b/spec/graphql/types/design_management/design_type_spec.rb @@ -5,8 +5,10 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['Design'] do specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) } + specify { expect(described_class.interfaces).to include(Types::TodoableInterface) } + it_behaves_like 'a GraphQL type with design fields' do - let(:extra_design_fields) { %i[notes current_user_todos discussions versions] } + let(:extra_design_fields) { %i[notes current_user_todos discussions versions web_url] } let_it_be(:design) { create(:design, :with_versions) } let(:object_id) { GitlabSchema.id_from_object(design) } let_it_be(:object_id_b) { GitlabSchema.id_from_object(create(:design, :with_versions)) } diff --git a/spec/graphql/types/global_id_type_spec.rb b/spec/graphql/types/global_id_type_spec.rb index e7e69cfad9e..8df92c818fc 100644 --- a/spec/graphql/types/global_id_type_spec.rb +++ b/spec/graphql/types/global_id_type_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Types::GlobalIDType do let(:gid) { project.to_global_id } it 'is has the correct name' do - expect(described_class.to_graphql.name).to eq('GlobalID') + expect(described_class.graphql_name).to eq('GlobalID') end describe '.coerce_result' do @@ -63,7 +63,7 @@ RSpec.describe Types::GlobalIDType do let(:type) { ::Types::GlobalIDType[::Project] } it 'is has the correct name' do - expect(type.to_graphql.name).to eq('ProjectID') + expect(type.graphql_name).to eq('ProjectID') end context 'the GID is appropriate' do @@ -126,7 +126,7 @@ RSpec.describe Types::GlobalIDType do let(:deprecating_gid) { Gitlab::GlobalId.build(model_name: 'Issue', id: issue.id) } it 'appends the description with a deprecation notice for the old Global ID' do - expect(type.to_graphql.description).to include('The older format `"gid://gitlab/OldIssue/1"` was deprecated in 10.0') + expect(type.description).to include('The older format `"gid://gitlab/OldIssue/1"` was deprecated in 10.0') end describe 'coercing input against the type (parsing the Global ID string when supplied as an argument)' do @@ -242,7 +242,7 @@ RSpec.describe Types::GlobalIDType do let(:type) { ::Types::GlobalIDType[::Ci::Build] } it 'is has a valid GraphQL identifier for a name' do - expect(type.to_graphql.name).to eq('CiBuildID') + expect(type.graphql_name).to eq('CiBuildID') end end @@ -376,4 +376,10 @@ RSpec.describe Types::GlobalIDType do expect(described_class.model_name_to_graphql_name('DesignManagement::Design')).to eq('DesignManagementDesignID') end end + + describe '.[]' do + it 'returns a custom class for work items' do + expect(described_class[::WorkItem]).to eq(::Types::WorkItemIdType) + end + end end diff --git a/spec/graphql/types/group_member_type_spec.rb b/spec/graphql/types/group_member_type_spec.rb index b1cb8e572ad..389295f3a39 100644 --- a/spec/graphql/types/group_member_type_spec.rb +++ b/spec/graphql/types/group_member_type_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Types::GroupMemberType do it 'has the expected fields' do expected_fields = %w[ - access_level created_by created_at updated_at expires_at group + access_level created_by created_at updated_at expires_at group notification_email ] expect(described_class).to include_graphql_fields(*expected_fields) diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb index 5ab8845246a..e9e92bbdc85 100644 --- a/spec/graphql/types/merge_request_type_spec.rb +++ b/spec/graphql/types/merge_request_type_spec.rb @@ -13,6 +13,8 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) } + specify { expect(described_class.interfaces).to include(Types::TodoableInterface) } + it 'has the expected fields' do expected_fields = %w[ notes discussions user_permissions id iid title title_html description @@ -33,7 +35,7 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do total_time_spent human_time_estimate human_total_time_spent reference author merged_at commit_count current_user_todos conflicts auto_merge_enabled approved_by source_branch_protected default_merge_commit_message_with_description squash_on_merge available_auto_merge_strategies - has_ci mergeable commits commits_without_merge_commits squash security_auto_fix default_squash_commit_message + has_ci mergeable commits committers commits_without_merge_commits squash security_auto_fix default_squash_commit_message auto_merge_strategy merge_user ] diff --git a/spec/graphql/types/merge_requests/assignee_type_spec.rb b/spec/graphql/types/merge_requests/assignee_type_spec.rb new file mode 100644 index 00000000000..d67d20860b2 --- /dev/null +++ b/spec/graphql/types/merge_requests/assignee_type_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MergeRequestAssignee'] do + it_behaves_like "a user type with merge request interaction type" +end diff --git a/spec/graphql/types/merge_requests/author_type_spec.rb b/spec/graphql/types/merge_requests/author_type_spec.rb new file mode 100644 index 00000000000..2a5a31f210c --- /dev/null +++ b/spec/graphql/types/merge_requests/author_type_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MergeRequestAuthor'] do + it_behaves_like "a user type with merge request interaction type" +end diff --git a/spec/graphql/types/merge_requests/participant_type_spec.rb b/spec/graphql/types/merge_requests/participant_type_spec.rb new file mode 100644 index 00000000000..083762c7064 --- /dev/null +++ b/spec/graphql/types/merge_requests/participant_type_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['MergeRequestParticipant'] do + it_behaves_like "a user type with merge request interaction type" +end diff --git a/spec/graphql/types/merge_requests/reviewer_type_spec.rb b/spec/graphql/types/merge_requests/reviewer_type_spec.rb index 4d357a922f8..92cb51df27a 100644 --- a/spec/graphql/types/merge_requests/reviewer_type_spec.rb +++ b/spec/graphql/types/merge_requests/reviewer_type_spec.rb @@ -3,51 +3,5 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['MergeRequestReviewer'] do - specify { expect(described_class).to require_graphql_authorizations(:read_user) } - - it 'has the expected fields' do - expected_fields = %w[ - id - bot - user_permissions - snippets - name - username - email - publicEmail - avatarUrl - webUrl - webPath - todos - state - status - location - authoredMergeRequests - assignedMergeRequests - reviewRequestedMergeRequests - groupMemberships - groupCount - projectMemberships - starredProjects - callouts - merge_request_interaction - namespace - timelogs - groups - ] - - expect(described_class).to have_graphql_fields(*expected_fields) - end - - describe '#merge_request_interaction' do - subject { described_class.fields['mergeRequestInteraction'] } - - it 'returns the correct type' do - is_expected.to have_graphql_type(Types::UserMergeRequestInteractionType) - end - - it 'has the correct arguments' do - is_expected.to have_attributes(arguments: be_empty) - end - end + it_behaves_like "a user type with merge request interaction type" end diff --git a/spec/graphql/types/projects/base_service_type_spec.rb b/spec/graphql/types/projects/base_service_type_spec.rb index 423cea860d7..43a680bc9c2 100644 --- a/spec/graphql/types/projects/base_service_type_spec.rb +++ b/spec/graphql/types/projects/base_service_type_spec.rb @@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['BaseService'] do specify { expect(described_class.graphql_name).to eq('BaseService') } it 'has basic expected fields' do - expect(described_class).to have_graphql_fields(:type, :active) + expect(described_class).to have_graphql_fields(:type, :active, :service_type) end specify { expect(described_class).to require_graphql_authorizations(:admin_project) } diff --git a/spec/graphql/types/projects/jira_service_type_spec.rb b/spec/graphql/types/projects/jira_service_type_spec.rb index 9db580ac963..69cdcb0f46f 100644 --- a/spec/graphql/types/projects/jira_service_type_spec.rb +++ b/spec/graphql/types/projects/jira_service_type_spec.rb @@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['JiraService'] do specify { expect(described_class.graphql_name).to eq('JiraService') } it 'has basic expected fields' do - expect(described_class).to have_graphql_fields(:type, :active, :projects) + expect(described_class).to have_graphql_fields(:type, :active, :projects, :service_type) end specify { expect(described_class).to require_graphql_authorizations(:admin_project) } diff --git a/spec/graphql/types/projects/service_type_enum_spec.rb b/spec/graphql/types/projects/service_type_enum_spec.rb new file mode 100644 index 00000000000..ead69e60f6c --- /dev/null +++ b/spec/graphql/types/projects/service_type_enum_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['ServiceType'] do + it 'exposes all the existing project services' do + expect(described_class.values.keys).to include(*core_service_enums) + end + + def core_service_enums + %w[ + ASANA_SERVICE + ASSEMBLA_SERVICE + BAMBOO_SERVICE + BUGZILLA_SERVICE + BUILDKITE_SERVICE + CAMPFIRE_SERVICE + CONFLUENCE_SERVICE + CUSTOM_ISSUE_TRACKER_SERVICE + DATADOG_SERVICE + DISCORD_SERVICE + DRONE_CI_SERVICE + EMAILS_ON_PUSH_SERVICE + EWM_SERVICE + EXTERNAL_WIKI_SERVICE + FLOWDOCK_SERVICE + HANGOUTS_CHAT_SERVICE + IRKER_SERVICE + JENKINS_SERVICE + JIRA_SERVICE + MATTERMOST_SERVICE + MATTERMOST_SLASH_COMMANDS_SERVICE + MICROSOFT_TEAMS_SERVICE + PACKAGIST_SERVICE + PIPELINES_EMAIL_SERVICE + PIVOTALTRACKER_SERVICE + PROMETHEUS_SERVICE + PUSHOVER_SERVICE + REDMINE_SERVICE + SHIMO_SERVICE + SLACK_SERVICE + SLACK_SLASH_COMMANDS_SERVICE + TEAMCITY_SERVICE + UNIFY_CIRCUIT_SERVICE + WEBEX_TEAMS_SERVICE + YOUTRACK_SERVICE + ZENTAO_SERVICE + ] + end + + it 'coerces values correctly' do + integration = build(:jenkins_integration) + expect(described_class.coerce_isolated_result(integration.type)).to eq 'JENKINS_SERVICE' + end +end diff --git a/spec/graphql/types/projects/service_type_spec.rb b/spec/graphql/types/projects/service_type_spec.rb index 0bffdfd629d..1a6a128544e 100644 --- a/spec/graphql/types/projects/service_type_spec.rb +++ b/spec/graphql/types/projects/service_type_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Types::Projects::ServiceType do - specify { expect(described_class).to have_graphql_fields(:type, :active) } + specify { expect(described_class).to have_graphql_fields(:type, :service_type, :active) } describe ".resolve_type" do it 'resolves the corresponding type for objects' do diff --git a/spec/graphql/types/projects/services_enum_spec.rb b/spec/graphql/types/projects/services_enum_spec.rb deleted file mode 100644 index 00427e1d580..00000000000 --- a/spec/graphql/types/projects/services_enum_spec.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe GitlabSchema.types['ServiceType'] do - it 'exposes all the existing project services' do - expect(described_class.values.keys).to match_array(available_services_enum) - end - - def available_services_enum - ::Integration.available_integration_types(include_dev: false).map(&:underscore).map(&:upcase) - end -end diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb index 49f0980bd08..8b8c44c10f6 100644 --- a/spec/graphql/types/query_type_spec.rb +++ b/spec/graphql/types/query_type_spec.rb @@ -29,6 +29,7 @@ RSpec.describe GitlabSchema.types['Query'] do timelogs board_list topics + gitpod_enabled ] expect(described_class).to have_graphql_fields(*expected_fields).at_least diff --git a/spec/graphql/types/repository/blob_type_spec.rb b/spec/graphql/types/repository/blob_type_spec.rb index 565341d15b9..a813ef85e6e 100644 --- a/spec/graphql/types/repository/blob_type_spec.rb +++ b/spec/graphql/types/repository/blob_type_spec.rb @@ -25,12 +25,15 @@ RSpec.describe Types::Repository::BlobType do :raw_path, :replace_path, :pipeline_editor_path, + :gitpod_blob_url, :find_file_path, :blame_path, :history_path, :permalink_path, :environment_formatted_external_url, :environment_external_url_for_route_map, + :code_navigation_path, + :project_blob_path_root, :code_owners, :simple_viewer, :rich_viewer, @@ -42,6 +45,7 @@ RSpec.describe Types::Repository::BlobType do :external_storage_url, :fork_and_edit_path, :ide_fork_and_edit_path, + :fork_and_view_path, :language ) end diff --git a/spec/graphql/types/saved_reply_type_spec.rb b/spec/graphql/types/saved_reply_type_spec.rb new file mode 100644 index 00000000000..3bf4d823588 --- /dev/null +++ b/spec/graphql/types/saved_reply_type_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['SavedReply'] do + specify { expect(described_class.graphql_name).to eq('SavedReply') } + + it 'has all the required fields' do + expect(described_class).to have_graphql_fields(:id, :content, :name) + end + + specify { expect(described_class).to require_graphql_authorizations(:read_saved_replies) } +end diff --git a/spec/graphql/types/todo_type_spec.rb b/spec/graphql/types/todo_type_spec.rb index 15b6195ec5c..8de63ebfda5 100644 --- a/spec/graphql/types/todo_type_spec.rb +++ b/spec/graphql/types/todo_type_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['Todo'] do it 'has the correct fields' do - expected_fields = [:id, :project, :group, :author, :action, :target_type, :body, :state, :created_at] + expected_fields = [:id, :project, :group, :author, :action, :target, :target_type, :body, :state, :created_at] expect(described_class).to have_graphql_fields(*expected_fields) end diff --git a/spec/graphql/types/todoable_interface_spec.rb b/spec/graphql/types/todoable_interface_spec.rb new file mode 100644 index 00000000000..bafd89fbf59 --- /dev/null +++ b/spec/graphql/types/todoable_interface_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::TodoableInterface do + it 'exposes the expected fields' do + expected_fields = %i[ + web_url + ] + + expect(described_class).to have_graphql_fields(*expected_fields) + end + + describe ".resolve_type" do + it 'knows the correct type for objects' do + expect(described_class.resolve_type(build(:issue), {})).to eq(Types::IssueType) + expect(described_class.resolve_type(build(:merge_request), {})).to eq(Types::MergeRequestType) + expect(described_class.resolve_type(build(:design), {})).to eq(Types::DesignManagement::DesignType) + expect(described_class.resolve_type(build(:alert_management_alert), {})).to eq(Types::AlertManagement::AlertType) + expect(described_class.resolve_type(build(:commit), {})).to eq(Types::CommitType) + end + + it 'raises an error for an unknown type' do + project = build(:project) + + expect { described_class.resolve_type(project, {}) }.to raise_error("Unknown GraphQL type for #{project}") + end + end +end diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb index a2fc8f4c954..c913a4c3662 100644 --- a/spec/graphql/types/user_type_spec.rb +++ b/spec/graphql/types/user_type_spec.rb @@ -39,6 +39,10 @@ RSpec.describe GitlabSchema.types['User'] do namespace timelogs groups + gitpodEnabled + preferencesGitpodPath + profileEnableGitpodPath + savedReplies ] expect(described_class).to have_graphql_fields(*expected_fields) @@ -49,10 +53,13 @@ RSpec.describe GitlabSchema.types['User'] do let_it_be(:user) { create(:user) } let_it_be(:requested_user) { create(:user, name: 'John Smith') } let_it_be(:requested_project_bot) { create(:user, :project_bot, name: 'Project bot') } + let_it_be(:requested_group_bot) { create(:user, :project_bot, name: 'Group bot') } let_it_be(:project) { create(:project, :public) } + let_it_be(:group) { create(:group, :public) } before do project.add_maintainer(requested_project_bot) + group.add_maintainer(requested_group_bot) end let(:username) { requested_user.username } @@ -120,6 +127,50 @@ RSpec.describe GitlabSchema.types['User'] do end end end + + context 'a group bot' do + let(:username) { requested_group_bot.username } + + context 'when requester is nil' do + let(:current_user) { nil } + + it 'returns `****`' do + expect(user_name).to eq('****') + end + end + + context 'when the requester is not a group member' do + it 'returns `Group bot` for a non group member in a public group' do + expect(user_name).to eq('Group bot') + end + + context 'in a private group' do + let(:group) { create(:group, :private) } + + it 'returns `****` for a non group member in a private group' do + expect(user_name).to eq('****') + end + end + end + + context 'with a group member' do + before do + group.add_guest(user) + end + + it 'returns `Group bot` for a group member' do + expect(user_name).to eq('Group bot') + end + + context 'in a private group' do + let(:group) { create(:group, :private) } + + it 'returns `Group bot` for a group member in a private group' do + expect(user_name).to eq('Group bot') + end + end + end + end end end @@ -139,6 +190,14 @@ RSpec.describe GitlabSchema.types['User'] do expect(subject).to eq('Project bot') end end + + context 'a group bot' do + let(:username) { requested_group_bot.username } + + it 'returns name' do + expect(subject).to eq('Group bot') + end + end end end diff --git a/spec/graphql/types/work_item_id_type_spec.rb b/spec/graphql/types/work_item_id_type_spec.rb new file mode 100644 index 00000000000..dc02401a3d0 --- /dev/null +++ b/spec/graphql/types/work_item_id_type_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::WorkItemIdType do + let_it_be(:project) { create(:project) } + let_it_be(:work_item) { create(:work_item, project: project) } + let_it_be(:issue) { create(:issue, project: project) } + + let(:work_item_gid) { work_item.to_gid } + let(:issue_gid) { issue.to_gid } + let(:ctx) { {} } + + describe '.coerce_input' do + it 'can coerce valid issue input' do + coerced = described_class.coerce_input(issue_gid.to_s, ctx) + + expect(coerced).to eq(WorkItem.find(issue.id).to_gid) + end + + it 'can coerce valid work item input' do + coerced = described_class.coerce_input(work_item_gid.to_s, ctx) + + expect(coerced).to eq(work_item_gid) + end + + it 'fails for other input types' do + project_gid = project.to_gid + + expect { described_class.coerce_input(project_gid.to_s, ctx) } + .to raise_error(GraphQL::CoercionError, "#{project_gid.to_s.inspect} does not represent an instance of WorkItem") + end + end + + describe '.coerce_result' do + it 'can coerce issue results and return a WorkItem global ID' do + expect(described_class.coerce_result(issue_gid, ctx)).to eq(WorkItem.find(issue.id).to_gid.to_s) + end + + it 'can coerce work item results' do + expect(described_class.coerce_result(work_item_gid, ctx)).to eq(work_item_gid.to_s) + end + + it 'fails for other input types' do + project_gid = project.to_gid + + expect { described_class.coerce_result(project_gid, ctx) } + .to raise_error(GraphQL::CoercionError, "Expected a WorkItem ID, got #{project_gid}") + end + end +end diff --git a/spec/graphql/types/work_item_type_spec.rb b/spec/graphql/types/work_item_type_spec.rb new file mode 100644 index 00000000000..6a5b4a0882e --- /dev/null +++ b/spec/graphql/types/work_item_type_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['WorkItem'] do + specify { expect(described_class.graphql_name).to eq('WorkItem') } + + specify { expect(described_class).to require_graphql_authorizations(:read_work_item) } + + it 'has specific fields' do + fields = %i[description description_html id iid lock_version state title title_html work_item_type] + + fields.each do |field_name| + expect(described_class).to have_graphql_fields(*fields) + end + end +end |