diff options
Diffstat (limited to 'spec/support/shared_examples/graphql')
5 files changed, 143 insertions, 12 deletions
diff --git a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb index bb4270d7db6..fc795012ce7 100644 --- a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb +++ b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb @@ -21,13 +21,13 @@ RSpec.shared_examples 'a mutation which can mutate a spammable' do end end - describe "#with_spam_action_response_fields" do + describe "#spam_action_response_fields" do it 'resolves with spam action fields' do subject # NOTE: We do not need to assert on the specific values of spam action fields here, we only need - # to verify that #with_spam_action_response_fields was invoked and that the fields are present in the - # response. The specific behavior of #with_spam_action_response_fields is covered in the + # to verify that #spam_action_response_fields was invoked and that the fields are present in the + # response. The specific behavior of #spam_action_response_fields is covered in the # HasSpamActionResponseFields unit tests. expect(mutation_response.keys) .to include('spam', 'spamLogId', 'needsCaptchaResponse', 'captchaSiteKey') diff --git a/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb index cfa12171b7e..022e2308517 100644 --- a/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb +++ b/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb @@ -10,22 +10,40 @@ RSpec.shared_examples 'an assignable resource' do describe '#resolve' do let_it_be(:assignee) { create(:user) } let_it_be(:assignee2) { create(:user) } + let(:assignee_usernames) { [assignee.username] } let(:mutated_resource) { subject[resource.class.name.underscore.to_sym] } + let(:mode) { described_class.arguments['operationMode'].default_value } - subject { mutation.resolve(project_path: resource.project.full_path, iid: resource.iid, assignee_usernames: assignee_usernames) } - - before do - resource.project.add_developer(assignee) - resource.project.add_developer(assignee2) + subject do + mutation.resolve(project_path: resource.project.full_path, + iid: resource.iid, + operation_mode: mode, + assignee_usernames: assignee_usernames) end it 'raises an error if the resource is not accessible to the user' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) end + it 'does not change assignees if the resource is not accessible to the assignees' do + resource.project.add_developer(user) + + expect { subject }.not_to change { resource.reload.assignee_ids } + end + + it 'returns an operational error if the resource is not accessible to the assignees' do + resource.project.add_developer(user) + + result = subject + + expect(result[:errors]).to include a_string_matching(/Cannot assign/) + end + context 'when the user can update the resource' do before do + resource.project.add_developer(assignee) + resource.project.add_developer(assignee2) resource.project.add_developer(user) end diff --git a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb index f78ea364147..eaeb5faee3b 100644 --- a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb +++ b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb @@ -44,7 +44,7 @@ # end # end # -RSpec.shared_examples 'sorted paginated query' do +RSpec.shared_examples 'sorted paginated query' do |conditions = {}| # Provided as a convenience when constructing queries using string concatenation let(:page_info) { 'pageInfo { startCursor endCursor }' } # Convenience for using default implementation of pagination_results_data @@ -123,6 +123,16 @@ RSpec.shared_examples 'sorted paginated query' do expect(results).to eq first_page end end + + context 'when last and sort params are present', if: conditions[:is_reversible] do + let(:params) { sort_argument.merge(last: 1) } + + it 'fetches last elements without error' do + post_graphql(pagination_query(params), current_user: current_user) + + expect(results.first).to eq(expected_results.last) + end + end end end end diff --git a/spec/support/shared_examples/graphql/spam_protection_shared_examples.rb b/spec/support/shared_examples/graphql/spam_protection_shared_examples.rb new file mode 100644 index 00000000000..8fb89a4f80e --- /dev/null +++ b/spec/support/shared_examples/graphql/spam_protection_shared_examples.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples 'has spam protection' do + include AfterNextHelpers + + describe '#check_spam_action_response!' do + let(:variables) { nil } + let(:headers) { {} } + let(:spam_log_id) { 123 } + let(:captcha_site_key) { 'abc123' } + + def send_request + post_graphql_mutation(mutation, current_user: current_user) + end + + before do + allow_next(mutation_class).to receive(:spam_action_response_fields).and_return( + spam: spam, + needs_captcha_response: render_captcha, + spam_log_id: spam_log_id, + captcha_site_key: captcha_site_key + ) + end + + context 'when the object is spam (DISALLOW)' do + shared_examples 'disallow response' do + it 'informs the client that the request was denied as spam' do + send_request + + expect(graphql_errors) + .to contain_exactly a_hash_including('message' => ::Mutations::SpamProtection::SPAM_DISALLOWED_MESSAGE) + expect(graphql_errors) + .to contain_exactly a_hash_including('extensions' => { "spam" => true }) + end + end + + let(:spam) { true } + + context 'and no CAPTCHA is available' do + let(:render_captcha) { false } + + it_behaves_like 'disallow response' + end + + context 'and a CAPTCHA is required' do + let(:render_captcha) { true } + + it_behaves_like 'disallow response' + end + end + + context 'when the object is not spam (CONDITIONAL ALLOW)' do + let(:spam) { false } + + context 'and no CAPTCHA is required' do + let(:render_captcha) { false } + + it 'does not return a to-level error' do + send_request + + expect(graphql_errors).to be_blank + end + end + + context 'and a CAPTCHA is required' do + let(:render_captcha) { true } + + it 'informs the client that the request may be retried after solving the CAPTCHA' do + send_request + + expect(graphql_errors) + .to contain_exactly a_hash_including('message' => ::Mutations::SpamProtection::NEEDS_CAPTCHA_RESPONSE_MESSAGE) + expect(graphql_errors) + .to contain_exactly a_hash_including('extensions' => { + "captcha_site_key" => captcha_site_key, + "needs_captcha_response" => true, + "spam_log_id" => spam_log_id + }) + end + end + end + end +end diff --git a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb index bc091a678e2..efb2c466f70 100644 --- a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb +++ b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb @@ -13,18 +13,18 @@ RSpec.shared_examples 'Gitlab-style deprecations' do it 'raises an error if a required property is missing', :aggregate_failures do expect { subject(deprecated: { milestone: '1.10' }) }.to raise_error( ArgumentError, - 'Please provide a `reason` within `deprecated`' + include("Reason can't be blank") ) expect { subject(deprecated: { reason: 'Deprecation reason' }) }.to raise_error( ArgumentError, - 'Please provide a `milestone` within `deprecated`' + include("Milestone can't be blank") ) end it 'raises an error if milestone is not a String', :aggregate_failures do expect { subject(deprecated: { milestone: 1.10, reason: 'Deprecation reason' }) }.to raise_error( ArgumentError, - '`milestone` must be a `String`' + include("Milestone must be a string") ) end end @@ -49,4 +49,22 @@ RSpec.shared_examples 'Gitlab-style deprecations' do expect(deprecable.description).to be_nil end + + it 'adds information about the replacement if provided' do + deprecable = subject(deprecated: { milestone: '1.10', reason: :renamed, replacement: 'Foo.bar' }) + + expect(deprecable.deprecation_reason).to include 'Please use `Foo.bar`' + end + + it 'supports named reasons: renamed' do + deprecable = subject(deprecated: { milestone: '1.10', reason: :renamed }) + + expect(deprecable.deprecation_reason).to include 'This was renamed.' + end + + it 'supports named reasons: discouraged' do + deprecable = subject(deprecated: { milestone: '1.10', reason: :discouraged }) + + expect(deprecable.deprecation_reason).to include 'Use of this is not recommended.' + end end |