Commit 300e027f authored by David Kim's avatar David Kim

Merge branch 'ajk-rubocop-fixes-13984' into 'master'

Fix todo-ed rubocop violations

See merge request gitlab-org/gitlab!56399
parents d6b7ec8d 52c415ff
...@@ -124,7 +124,7 @@ class GitlabSchema < GraphQL::Schema ...@@ -124,7 +124,7 @@ class GitlabSchema < GraphQL::Schema
raise Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID." unless gid raise Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID." unless gid
if expected_type && !gid.model_class.ancestors.include?(expected_type) if expected_type && gid.model_class.ancestors.exclude?(expected_type)
vars = { global_id: global_id, expected_type: expected_type } vars = { global_id: global_id, expected_type: expected_type }
msg = _('%{global_id} is not a valid ID for %{expected_type}.') % vars msg = _('%{global_id} is not a valid ID for %{expected_type}.') % vars
raise Gitlab::Graphql::Errors::ArgumentError, msg raise Gitlab::Graphql::Errors::ArgumentError, msg
......
...@@ -39,9 +39,7 @@ module Resolvers ...@@ -39,9 +39,7 @@ module Resolvers
as_single << block as_single << block
# Have we been called after defining the single version of this resolver? # Have we been called after defining the single version of this resolver?
if @single.present? @single.instance_exec(&block) if @single.present?
@single.instance_exec(&block)
end
end end
def self.as_single def self.as_single
...@@ -90,7 +88,7 @@ module Resolvers ...@@ -90,7 +88,7 @@ module Resolvers
def self.last def self.last
parent = self parent = self
@last ||= Class.new(self.single) do @last ||= Class.new(single) do
type parent.singular_type, null: true type parent.singular_type, null: true
def select_result(results) def select_result(results)
......
...@@ -33,12 +33,18 @@ module Resolvers ...@@ -33,12 +33,18 @@ module Resolvers
argument :source_branches, [GraphQL::STRING_TYPE], argument :source_branches, [GraphQL::STRING_TYPE],
required: false, required: false,
as: :source_branch, as: :source_branch,
description: 'Array of source branch names. All resolved merge requests will have one of these branches as their source.' description: <<~DESC
Array of source branch names.
All resolved merge requests will have one of these branches as their source.
DESC
argument :target_branches, [GraphQL::STRING_TYPE], argument :target_branches, [GraphQL::STRING_TYPE],
required: false, required: false,
as: :target_branch, as: :target_branch,
description: 'Array of target branch names. All resolved merge requests will have one of these branches as their target.' description: <<~DESC
Array of target branch names.
All resolved merge requests will have one of these branches as their target.
DESC
argument :state, ::Types::MergeRequestStateEnum, argument :state, ::Types::MergeRequestStateEnum,
required: false, required: false,
......
...@@ -4,13 +4,21 @@ module Resolvers ...@@ -4,13 +4,21 @@ module Resolvers
class UserMergeRequestsResolverBase < MergeRequestsResolver class UserMergeRequestsResolverBase < MergeRequestsResolver
include ResolvesProject include ResolvesProject
argument :project_path, GraphQL::STRING_TYPE, argument :project_path,
type: GraphQL::STRING_TYPE,
required: false, required: false,
description: 'The full-path of the project the authored merge requests should be in. Incompatible with projectId.' description: <<~DESC
The full-path of the project the authored merge requests should be in.
Incompatible with projectId.
DESC
argument :project_id, ::Types::GlobalIDType[::Project], argument :project_id,
type: ::Types::GlobalIDType[::Project],
required: false, required: false,
description: 'The global ID of the project the authored merge requests should be in. Incompatible with projectPath.' description: <<~DESC
The global ID of the project the authored merge requests should be in.
Incompatible with projectPath.
DESC
attr_reader :project attr_reader :project
alias_method :user, :object alias_method :user, :object
...@@ -22,8 +30,7 @@ module Resolvers ...@@ -22,8 +30,7 @@ module Resolvers
load_project(project_path, project_id) load_project(project_path, project_id)
return early_return unless can_read_project? return early_return unless can_read_project?
elsif args[:iids].present? elsif args[:iids].present?
raise ::Gitlab::Graphql::Errors::ArgumentError, raise ::Gitlab::Graphql::Errors::ArgumentError, 'iids requires projectPath or projectId'
'iids requires projectPath or projectId'
end end
super(**args) super(**args)
......
...@@ -21,7 +21,10 @@ module Types ...@@ -21,7 +21,10 @@ module Types
graphql_name(enum_mod.name) if use_name graphql_name(enum_mod.name) if use_name
description(enum_mod.description) if use_description description(enum_mod.description) if use_description
enum_mod.definition.each { |key, content| value(key.to_s.upcase, **content) } enum_mod.definition.each do |key, content|
desc = content.delete(:description)
value(key.to_s.upcase, description: desc, **content)
end
end end
def value(*args, **kwargs, &block) def value(*args, **kwargs, &block)
......
...@@ -7,7 +7,8 @@ module Resolvers ...@@ -7,7 +7,8 @@ module Resolvers
type Types::DastSiteProfileType.connection_type, null: true type Types::DastSiteProfileType.connection_type, null: true
when_single do when_single do
argument :id, ::Types::GlobalIDType[::DastSiteProfile], required: true, argument :id, ::Types::GlobalIDType[::DastSiteProfile],
required: true,
description: "ID of the site profile." description: "ID of the site profile."
end end
......
...@@ -6,11 +6,14 @@ module Resolvers ...@@ -6,11 +6,14 @@ module Resolvers
type Types::DastSiteValidationType.connection_type, null: true type Types::DastSiteValidationType.connection_type, null: true
argument :normalized_target_urls, [GraphQL::STRING_TYPE], required: false, argument :normalized_target_urls, [GraphQL::STRING_TYPE],
required: false,
description: 'Normalized URL of the target to be scanned.' description: 'Normalized URL of the target to be scanned.'
def resolve(**args) def resolve(**args)
DastSiteValidationsFinder.new(project_id: project.id, url_base: args[:normalized_target_urls], most_recent: true).execute DastSiteValidationsFinder
.new(project_id: project.id, url_base: args[:normalized_target_urls], most_recent: true)
.execute
end end
end end
end end
...@@ -7,44 +7,72 @@ module Types ...@@ -7,44 +7,72 @@ module Types
description 'Represents vulnerability finding of a security report on the pipeline.' description 'Represents vulnerability finding of a security report on the pipeline.'
field :report_type, VulnerabilityReportTypeEnum, null: true, field :report_type,
type: VulnerabilityReportTypeEnum,
null: true,
description: 'Type of the security report that found the vulnerability finding.' description: 'Type of the security report that found the vulnerability finding.'
field :name, GraphQL::STRING_TYPE, null: true, field :name,
type: GraphQL::STRING_TYPE,
null: true,
description: 'Name of the vulnerability finding.' description: 'Name of the vulnerability finding.'
field :severity, VulnerabilitySeverityEnum, null: true, field :severity,
type: VulnerabilitySeverityEnum,
null: true,
description: 'Severity of the vulnerability finding.' description: 'Severity of the vulnerability finding.'
field :confidence, GraphQL::STRING_TYPE, null: true, field :confidence,
type: GraphQL::STRING_TYPE,
null: true,
description: 'Type of the security report that found the vulnerability.' description: 'Type of the security report that found the vulnerability.'
field :scanner, VulnerabilityScannerType, null: true, field :scanner,
type: VulnerabilityScannerType,
null: true,
description: 'Scanner metadata for the vulnerability.' description: 'Scanner metadata for the vulnerability.'
field :identifiers, [VulnerabilityIdentifierType], null: false, field :identifiers,
type: [VulnerabilityIdentifierType],
null: false,
description: 'Identifiers of the vulnerabilit finding.' description: 'Identifiers of the vulnerabilit finding.'
field :project_fingerprint, GraphQL::STRING_TYPE, null: true, field :project_fingerprint,
type: GraphQL::STRING_TYPE,
null: true,
description: 'Name of the vulnerability finding.' description: 'Name of the vulnerability finding.'
field :uuid, GraphQL::STRING_TYPE, null: true, field :uuid,
type: GraphQL::STRING_TYPE,
null: true,
description: 'Name of the vulnerability finding.' description: 'Name of the vulnerability finding.'
field :project, ::Types::ProjectType, null: true, field :project,
type: ::Types::ProjectType,
null: true,
description: 'The project on which the vulnerability finding was found.' description: 'The project on which the vulnerability finding was found.'
field :description, GraphQL::STRING_TYPE, null: true, field :description,
type: GraphQL::STRING_TYPE,
null: true,
description: 'Description of the vulnerability finding.' description: 'Description of the vulnerability finding.'
field :location, VulnerabilityLocationType, null: true, field :location,
description: 'Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability.' type: VulnerabilityLocationType,
null: true,
description: <<~DESC.squish
Location metadata for the vulnerability.
Its fields depend on the type of security scan that found the vulnerability.
DESC
field :solution, GraphQL::STRING_TYPE, null: true, field :solution,
type: GraphQL::STRING_TYPE,
null: true,
description: "URL to the vulnerability's details page." description: "URL to the vulnerability's details page."
def location def location
object.location&.merge(report_type: object.report_type) object.location&.merge(report_type: object.report_type)
end end
end end
# rubocop: enable Graphql/AuthorizeTypes
end end
...@@ -10,7 +10,7 @@ RSpec.describe Resolvers::DastSiteProfileResolver do ...@@ -10,7 +10,7 @@ RSpec.describe Resolvers::DastSiteProfileResolver do
end end
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user, developer_projects: [project] ) } let_it_be(:developer) { create(:user, developer_projects: [project]) }
let_it_be(:dast_site_profile1) { create(:dast_site_profile, project: project) } let_it_be(:dast_site_profile1) { create(:dast_site_profile, project: project) }
let_it_be(:dast_site_profile2) { create(:dast_site_profile, project: project) } let_it_be(:dast_site_profile2) { create(:dast_site_profile, project: project) }
......
...@@ -57,12 +57,12 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -57,12 +57,12 @@ RSpec.describe GitlabSchema.types['Project'] do
it 'returns a list of analyzers enabled for the project' do it 'returns a list of analyzers enabled for the project' do
query_result = subject.dig('data', 'project', 'securityScanners', 'enabled') query_result = subject.dig('data', 'project', 'securityScanners', 'enabled')
expect(query_result).to match_array(%w(SAST DAST SECRET_DETECTION)) expect(query_result).to match_array(%w[SAST DAST SECRET_DETECTION])
end end
it 'returns a list of analyzers which were run in the last pipeline for the project' do it 'returns a list of analyzers which were run in the last pipeline for the project' do
query_result = subject.dig('data', 'project', 'securityScanners', 'pipelineRun') query_result = subject.dig('data', 'project', 'securityScanners', 'pipelineRun')
expect(query_result).to match_array(%w(DAST SAST)) expect(query_result).to match_array(%w[DAST SAST])
end end
end end
......
...@@ -123,7 +123,8 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do ...@@ -123,7 +123,8 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
let(:type) do let(:type) do
permissions = permission_collection permissions = permission_collection
type_factory do |type| type_factory do |type|
type.field :name, GraphQL::STRING_TYPE, null: true, type.field :name, GraphQL::STRING_TYPE,
null: true,
authorize: permissions authorize: permissions
end end
end end
...@@ -201,7 +202,8 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do ...@@ -201,7 +202,8 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
let(:query_type) do let(:query_type) do
query_factory do |query| query_factory do |query|
query.field :item, type, null: true, query.field :item, type,
null: true,
resolver: resolver, resolver: resolver,
authorize: permission_2 authorize: permission_2
end end
...@@ -288,8 +290,12 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do ...@@ -288,8 +290,12 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
let(:query_string) { '{ item(first: 1) { edges { node { name } } } }' } let(:query_string) { '{ item(first: 1) { edges { node { name } } } }' }
it 'only checks permissions for the first object' do it 'only checks permissions for the first object' do
expect(Ability).to receive(:allowed?).with(user, permission_single, test_object) { true } expect(Ability)
expect(Ability).not_to receive(:allowed?).with(user, permission_single, second_test_object) .to receive(:allowed?)
.with(user, permission_single, test_object)
.and_return(true)
expect(Ability)
.not_to receive(:allowed?).with(user, permission_single, second_test_object)
expect(subject.size).to eq(1) expect(subject.size).to eq(1)
end end
...@@ -330,10 +336,12 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do ...@@ -330,10 +336,12 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
end end
let(:project_type) do |type| let(:project_type) do |type|
issues = Issue.where(project: [visible_project, other_project]).order(id: :asc)
type_factory do |type| type_factory do |type|
type.graphql_name 'FakeProjectType' type.graphql_name 'FakeProjectType'
type.field :test_issues, issue_type.connection_type, null: false, type.field :test_issues, issue_type.connection_type,
resolver: new_resolver(Issue.where(project: [visible_project, other_project]).order(id: :asc)) null: false,
resolver: new_resolver(issues)
end end
end end
......
...@@ -56,10 +56,10 @@ RSpec.describe Mutations::DesignManagement::Upload do ...@@ -56,10 +56,10 @@ RSpec.describe Mutations::DesignManagement::Upload do
.map { |f| RenameableUpload.unique_file(f) } .map { |f| RenameableUpload.unique_file(f) }
end end
def creates_designs def creates_designs(&block)
prior_count = DesignManagement::Design.count prior_count = DesignManagement::Design.count
expect { yield }.not_to raise_error expect(&block).not_to raise_error
expect(DesignManagement::Design.count).to eq(prior_count + files.size) expect(DesignManagement::Design.count).to eq(prior_count + files.size)
end end
......
...@@ -7,6 +7,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -7,6 +7,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
include SortingHelper include SortingHelper
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:other_project) { create(:project, :repository) }
let_it_be(:milestone) { create(:milestone, project: project) } let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:other_user) { create(:user) } let_it_be(:other_user) { create(:user) }
...@@ -16,10 +17,17 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -16,10 +17,17 @@ RSpec.describe Resolvers::MergeRequestsResolver do
let_it_be(:merge_request_3) { create(:merge_request, :unique_branches, **common_attrs) } let_it_be(:merge_request_3) { create(:merge_request, :unique_branches, **common_attrs) }
let_it_be(:merge_request_4) { create(:merge_request, :unique_branches, :locked, **common_attrs) } let_it_be(:merge_request_4) { create(:merge_request, :unique_branches, :locked, **common_attrs) }
let_it_be(:merge_request_5) { create(:merge_request, :simple, :locked, **common_attrs) } let_it_be(:merge_request_5) { create(:merge_request, :simple, :locked, **common_attrs) }
let_it_be(:merge_request_6) { create(:labeled_merge_request, :unique_branches, labels: create_list(:label, 2, project: project), **common_attrs) } let_it_be(:merge_request_6) do
let_it_be(:merge_request_with_milestone) { create(:merge_request, :unique_branches, **common_attrs, milestone: milestone) } create(:labeled_merge_request, :unique_branches, **common_attrs, labels: create_list(:label, 2, project: project))
let_it_be(:other_project) { create(:project, :repository) } end
let_it_be(:other_merge_request) { create(:merge_request, source_project: other_project, target_project: other_project) }
let_it_be(:merge_request_with_milestone) do
create(:merge_request, :unique_branches, **common_attrs, milestone: milestone)
end
let_it_be(:other_merge_request) do
create(:merge_request, source_project: other_project, target_project: other_project)
end
let(:iid_1) { merge_request_1.iid } let(:iid_1) { merge_request_1.iid }
let(:iid_2) { merge_request_2.iid } let(:iid_2) { merge_request_2.iid }
...@@ -43,11 +51,14 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -43,11 +51,14 @@ RSpec.describe Resolvers::MergeRequestsResolver do
# SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = 2 # SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = 2
let(:queries_per_project) { 4 } let(:queries_per_project) { 4 }
context 'no arguments' do context 'without arguments' do
it 'returns all merge requests' do it 'returns all merge requests' do
result = resolve_mr(project) result = resolve_mr(project)
expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6, merge_request_with_milestone) expect(result).to contain_exactly(
merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5,
merge_request_6, merge_request_with_milestone
)
end end
it 'returns only merge requests that the current user can see' do it 'returns only merge requests that the current user can see' do
...@@ -57,7 +68,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -57,7 +68,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end end
end end
context 'by iid alone' do context 'with iid alone' do
it 'batch-resolves by target project full path and individual IID', :request_store do it 'batch-resolves by target project full path and individual IID', :request_store do
# 1 query for project_authorizations, and 1 for merge_requests # 1 query for project_authorizations, and 1 for merge_requests
result = batch_sync(max_queries: queries_per_project) do result = batch_sync(max_queries: queries_per_project) do
...@@ -83,7 +94,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -83,7 +94,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3) expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3)
end end
it 'can batch-resolve merge requests from different projects', :request_store, :use_clean_rails_memory_store_caching do it 'can batch-resolve merge requests from different projects', :request_store do
# 2 queries for project_authorizations, and 2 for merge_requests # 2 queries for project_authorizations, and 2 for merge_requests
results = batch_sync(max_queries: queries_per_project * 2) do results = batch_sync(max_queries: queries_per_project * 2) do
a = resolve_mr(project, iids: [iid_1]) a = resolve_mr(project, iids: [iid_1])
...@@ -121,7 +132,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -121,7 +132,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end end
end end
context 'by source branches' do context 'with source branches argument' do
it 'takes one argument' do it 'takes one argument' do
result = resolve_mr(project, source_branches: [merge_request_3.source_branch]) result = resolve_mr(project, source_branches: [merge_request_3.source_branch])
...@@ -131,13 +142,13 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -131,13 +142,13 @@ RSpec.describe Resolvers::MergeRequestsResolver do
it 'takes more than one argument' do it 'takes more than one argument' do
mrs = [merge_request_3, merge_request_4] mrs = [merge_request_3, merge_request_4]
branches = mrs.map(&:source_branch) branches = mrs.map(&:source_branch)
result = resolve_mr(project, source_branches: branches ) result = resolve_mr(project, source_branches: branches)
expect(result).to match_array(mrs) expect(result).to match_array(mrs)
end end
end end
context 'by target branches' do context 'with target branches argument' do
it 'takes one argument' do it 'takes one argument' do
result = resolve_mr(project, target_branches: [merge_request_3.target_branch]) result = resolve_mr(project, target_branches: [merge_request_3.target_branch])
...@@ -153,7 +164,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -153,7 +164,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end end
end end
context 'by state' do context 'with state argument' do
it 'takes one argument' do it 'takes one argument' do
result = resolve_mr(project, state: 'locked') result = resolve_mr(project, state: 'locked')
...@@ -161,7 +172,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -161,7 +172,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end end
end end
context 'by label' do context 'with label argument' do
let_it_be(:label) { merge_request_6.labels.first } let_it_be(:label) { merge_request_6.labels.first }
let_it_be(:with_label) { create(:labeled_merge_request, :closed, labels: [label], **common_attrs) } let_it_be(:with_label) { create(:labeled_merge_request, :closed, labels: [label], **common_attrs) }
...@@ -178,7 +189,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -178,7 +189,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end end
end end
context 'by merged_after and merged_before' do context 'with merged_after and merged_before arguments' do
before do before do
merge_request_1.metrics.update!(merged_at: 10.days.ago) merge_request_1.metrics.update!(merged_at: 10.days.ago)
end end
...@@ -196,7 +207,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -196,7 +207,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end end
end end
context 'by milestone' do context 'with milestone argument' do
it 'filters merge requests by milestone title' do it 'filters merge requests by milestone title' do
result = resolve_mr(project, milestone_title: milestone.title) result = resolve_mr(project, milestone_title: milestone.title)
...@@ -212,7 +223,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do ...@@ -212,7 +223,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
describe 'combinations' do describe 'combinations' do
it 'requires all filters' do it 'requires all filters' do
create(:merge_request, :closed, source_project: project, target_project: project, source_branch: merge_request_4.source_branch) create(:merge_request, :closed, **common_attrs, source_branch: merge_request_4.source_branch)
result = resolve_mr(project, source_branches: [merge_request_4.source_branch], state: 'locked') result = resolve_mr(project, source_branches: [merge_request_4.source_branch], state: 'locked')
......
...@@ -48,14 +48,14 @@ RSpec.describe GitlabSchema.types['AlertManagementPrometheusIntegration'] do ...@@ -48,14 +48,14 @@ RSpec.describe GitlabSchema.types['AlertManagementPrometheusIntegration'] do
end end
end end
context 'group integration' do describe 'a group integration' do
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:integration) { create(:prometheus_service, project: nil, group: group) } let_it_be(:integration) { create(:prometheus_service, project: nil, group: group) }
# Since it is impossible to authorize the parent here, given that the # Since it is impossible to authorize the parent here, given that the
# project is nil, all fields should be redacted: # project is nil, all fields should be redacted:
described_class.fields.keys.each do |field_name| described_class.fields.each_key do |field_name|
context "field: #{field_name}" do context "field: #{field_name}" do
it 'is redacted' do it 'is redacted' do
expect do expect do
......
...@@ -196,20 +196,20 @@ RSpec.describe Types::BaseObject do ...@@ -196,20 +196,20 @@ RSpec.describe Types::BaseObject do
end end
# For example a batchloaded association # For example a batchloaded association
context 'a lazy list' do describe 'a lazy list' do
it_behaves_like 'array member redaction', %w[lazyListOfYs] it_behaves_like 'array member redaction', %w[lazyListOfYs]
end end
# For example using a batchloader to map over a set of IDs # For example using a batchloader to map over a set of IDs
context 'a list of lazy items' do describe 'a list of lazy items' do
it_behaves_like 'array member redaction', %w[listOfLazyYs] it_behaves_like 'array member redaction', %w[listOfLazyYs]
end end
context 'an array connection of items' do describe 'an array connection of items' do
it_behaves_like 'array member redaction', %w[arrayYsConn nodes] it_behaves_like 'array member redaction', %w[arrayYsConn nodes]
end end
context 'an array connection of items, selecting edges' do describe 'an array connection of items, selecting edges' do
it_behaves_like 'array member redaction', %w[arrayYsConn edges node] it_behaves_like 'array member redaction', %w[arrayYsConn edges node]
end end
...@@ -222,7 +222,7 @@ RSpec.describe Types::BaseObject do ...@@ -222,7 +222,7 @@ RSpec.describe Types::BaseObject do
} }
} }
doc = ->(after) do doc = lambda do |after|
GraphQL.parse(<<~GQL) GraphQL.parse(<<~GQL)
query { query {
x { x {
...@@ -238,9 +238,7 @@ RSpec.describe Types::BaseObject do ...@@ -238,9 +238,7 @@ RSpec.describe Types::BaseObject do
} }
GQL GQL
end end
returned_items = ->(ids) do returned_items = ->(ids) { ids.to_a.map { |id| eq({ 'id' => id }) } }
ids.to_a.map { |id| eq({ 'id' => id }) }
end
query = GraphQL::Query.new(test_schema, document: doc[nil], context: data) query = GraphQL::Query.new(test_schema, document: doc[nil], context: data)
result = query.result.to_h result = query.result.to_h
......
...@@ -106,7 +106,8 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -106,7 +106,8 @@ RSpec.describe GitlabSchema.types['Project'] do
expect(secure_analyzers_prefix['type']).to eq('string') expect(secure_analyzers_prefix['type']).to eq('string')
expect(secure_analyzers_prefix['field']).to eq('SECURE_ANALYZERS_PREFIX') expect(secure_analyzers_prefix['field']).to eq('SECURE_ANALYZERS_PREFIX')
expect(secure_analyzers_prefix['label']).to eq('Image prefix') expect(secure_analyzers_prefix['label']).to eq('Image prefix')
expect(secure_analyzers_prefix['defaultValue']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers') expect(secure_analyzers_prefix['defaultValue'])
.to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
expect(secure_analyzers_prefix['value']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers') expect(secure_analyzers_prefix['value']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
expect(secure_analyzers_prefix['size']).to eq('LARGE') expect(secure_analyzers_prefix['size']).to eq('LARGE')
expect(secure_analyzers_prefix['options']).to be_nil expect(secure_analyzers_prefix['options']).to be_nil
...@@ -184,9 +185,11 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -184,9 +185,11 @@ RSpec.describe GitlabSchema.types['Project'] do
context 'when repository is accessible only by team members' do context 'when repository is accessible only by team members' do
it "returns no configuration" do it "returns no configuration" do
project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED, project.project_feature.update!(
merge_requests_access_level: ProjectFeature::DISABLED,
builds_access_level: ProjectFeature::DISABLED, builds_access_level: ProjectFeature::DISABLED,
repository_access_level: ProjectFeature::PRIVATE) repository_access_level: ProjectFeature::PRIVATE
)
secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration') secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration')
expect(secure_analyzers_prefix).to be_nil expect(secure_analyzers_prefix).to be_nil
...@@ -342,8 +345,13 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -342,8 +345,13 @@ RSpec.describe GitlabSchema.types['Project'] do
let_it_be(:project) { create(:project, :public) } let_it_be(:project) { create(:project, :public) }
context 'when project has Jira imports' do context 'when project has Jira imports' do
let_it_be(:jira_import1) { create(:jira_import_state, :finished, project: project, jira_project_key: 'AA', created_at: 2.days.ago) } let_it_be(:jira_import1) do
let_it_be(:jira_import2) { create(:jira_import_state, :finished, project: project, jira_project_key: 'BB', created_at: 5.days.ago) } create(:jira_import_state, :finished, project: project, jira_project_key: 'AA', created_at: 2.days.ago)
end
let_it_be(:jira_import2) do
create(:jira_import_state, :finished, project: project, jira_project_key: 'BB', created_at: 5.days.ago)
end
it 'retrieves the imports' do it 'retrieves the imports' do
expect(subject).to contain_exactly(jira_import1, jira_import2) expect(subject).to contain_exactly(jira_import1, jira_import2)
......
...@@ -12,7 +12,8 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do ...@@ -12,7 +12,8 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
authorize :read_the_thing authorize :read_the_thing
def initialize(user, found_object) def initialize(user, found_object)
@user, @found_object = user, found_object @user = user
@found_object = found_object
end end
def find_object def find_object
...@@ -40,16 +41,12 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do ...@@ -40,16 +41,12 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
before do before do
# don't allow anything by default # don't allow anything by default
allow(Ability).to receive(:allowed?) do allow(Ability).to receive(:allowed?).and_return(false)
false
end
end end
context 'when the user is allowed to perform the action' do context 'when the user is allowed to perform the action' do
before do before do
allow(Ability).to receive(:allowed?).with(user, :read_the_thing, project) do allow(Ability).to receive(:allowed?).with(user, :read_the_thing, project).and_return(true)
true
end
end end
describe '#authorized_find!' do describe '#authorized_find!' do
......
...@@ -3,10 +3,11 @@ require 'spec_helper' ...@@ -3,10 +3,11 @@ require 'spec_helper'
RSpec.describe 'GraphQL' do RSpec.describe 'GraphQL' do
include GraphqlHelpers include GraphqlHelpers
include AfterNextHelpers
let(:query) { graphql_query_for('echo', text: 'Hello world' ) } let(:query) { graphql_query_for('echo', text: 'Hello world') }
context 'logging' do describe 'logging' do
shared_examples 'logging a graphql query' do shared_examples 'logging a graphql query' do
let(:expected_params) do let(:expected_params) do
{ {
...@@ -51,19 +52,25 @@ RSpec.describe 'GraphQL' do ...@@ -51,19 +52,25 @@ RSpec.describe 'GraphQL' do
context 'when there is an error in the logger' do context 'when there is an error in the logger' do
before do before do
allow_any_instance_of(Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer).to receive(:process_variables).and_raise(StandardError.new("oh noes!")) logger_analyzer = GitlabSchema.query_analyzers.find do |qa|
qa.is_a? Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer
end
allow(logger_analyzer).to receive(:process_variables)
.and_raise(StandardError.new("oh noes!"))
end end
it 'logs the exception in Sentry and continues with the request' do it 'logs the exception in Sentry and continues with the request' do
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once) expect(Gitlab::ErrorTracking)
expect(Gitlab::GraphqlLogger).to receive(:info) .to receive(:track_and_raise_for_dev_exception).at_least(:once)
expect(Gitlab::GraphqlLogger)
.to receive(:info)
post_graphql(query, variables: {}) post_graphql(query, variables: {})
end end
end end
end end
context 'invalid variables' do context 'with invalid variables' do
it 'returns an error' do it 'returns an error' do
post_graphql(query, variables: "This is not JSON") post_graphql(query, variables: "This is not JSON")
...@@ -72,7 +79,7 @@ RSpec.describe 'GraphQL' do ...@@ -72,7 +79,7 @@ RSpec.describe 'GraphQL' do
end end
end end
context 'authentication', :allow_forgery_protection do describe 'authentication', :allow_forgery_protection do
let(:user) { create(:user) } let(:user) { create(:user) }
it 'allows access to public data without authentication' do it 'allows access to public data without authentication' do
...@@ -99,7 +106,7 @@ RSpec.describe 'GraphQL' do ...@@ -99,7 +106,7 @@ RSpec.describe 'GraphQL' do
expect(graphql_data['echo']).to eq("\"#{user.username}\" says: Hello world") expect(graphql_data['echo']).to eq("\"#{user.username}\" says: Hello world")
end end
context 'token authentication' do context 'with token authentication' do
let(:token) { create(:personal_access_token) } let(:token) { create(:personal_access_token) }
before do before do
...@@ -119,7 +126,7 @@ RSpec.describe 'GraphQL' do ...@@ -119,7 +126,7 @@ RSpec.describe 'GraphQL' do
context 'when the personal access token has no api scope' do context 'when the personal access token has no api scope' do
it 'does not log the user in' do it 'does not log the user in' do
token.update(scopes: [:read_user]) token.update!(scopes: [:read_user])
post_graphql(query, headers: { 'PRIVATE-TOKEN' => token.token }) post_graphql(query, headers: { 'PRIVATE-TOKEN' => token.token })
...@@ -136,7 +143,11 @@ RSpec.describe 'GraphQL' do ...@@ -136,7 +143,11 @@ RSpec.describe 'GraphQL' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:query) do let(:query) do
graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id)) graphql_query_for(
:project,
{ full_path: project.full_path },
'id'
)
end end
before do before do
...@@ -202,8 +213,8 @@ RSpec.describe 'GraphQL' do ...@@ -202,8 +213,8 @@ RSpec.describe 'GraphQL' do
let_it_be(:issues) { create_list(:issue, 10, project: project, created_at: Time.now.change(usec: 200)) } let_it_be(:issues) { create_list(:issue, 10, project: project, created_at: Time.now.change(usec: 200)) }
let(:page_size) { 6 } let(:page_size) { 6 }
let(:issues_edges) { %w(data project issues edges) } let(:issues_edges) { %w[project issues edges] }
let(:end_cursor) { %w(data project issues pageInfo endCursor) } let(:end_cursor) { %w[project issues pageInfo endCursor] }
let(:query) do let(:query) do
<<~GRAPHQL <<~GRAPHQL
query project($fullPath: ID!, $first: Int, $after: String) { query project($fullPath: ID!, $first: Int, $after: String) {
...@@ -217,16 +228,10 @@ RSpec.describe 'GraphQL' do ...@@ -217,16 +228,10 @@ RSpec.describe 'GraphQL' do
GRAPHQL GRAPHQL
end end
# TODO: Switch this to use `post_graphql`
# This is not performing an actual GraphQL request because the
# variables end up being strings when passed through the `post_graphql`
# helper.
#
# https://gitlab.com/gitlab-org/gitlab/-/issues/222432
def execute_query(after: nil) def execute_query(after: nil)
GitlabSchema.execute( post_graphql(
query, query,
context: { current_user: nil }, current_user: nil,
variables: { variables: {
fullPath: project.full_path, fullPath: project.full_path,
first: page_size, first: page_size,
...@@ -240,14 +245,16 @@ RSpec.describe 'GraphQL' do ...@@ -240,14 +245,16 @@ RSpec.describe 'GraphQL' do
expect(Gitlab::Graphql::Pagination::Keyset::QueryBuilder) expect(Gitlab::Graphql::Pagination::Keyset::QueryBuilder)
.to receive(:new).with(anything, anything, hash_including('created_at'), anything).and_call_original .to receive(:new).with(anything, anything, hash_including('created_at'), anything).and_call_original
first_page = execute_query execute_query
first_page = graphql_data
edges = first_page.dig(*issues_edges) edges = first_page.dig(*issues_edges)
cursor = first_page.dig(*end_cursor) cursor = first_page.dig(*end_cursor)
expect(edges.count).to eq(6) expect(edges.count).to eq(6)
expect(edges.last['node']['iid']).to eq(issues[4].iid.to_s) expect(edges.last['node']['iid']).to eq(issues[4].iid.to_s)
second_page = execute_query(after: cursor) execute_query(after: cursor)
second_page = graphql_data
edges = second_page.dig(*issues_edges) edges = second_page.dig(*issues_edges)
expect(edges.count).to eq(4) expect(edges.count).to eq(4)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment