Commit 9aae0070 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch '267966-remove-deprecated-graphql-fields' into 'master'

Remove graphql deprecated fields

See merge request gitlab-org/gitlab!63293
parents 59c3615c 89009fc7
...@@ -7,12 +7,6 @@ module Mutations ...@@ -7,12 +7,6 @@ module Mutations
authorize :update_user authorize :update_user
field :updated_ids,
[::Types::GlobalIDType[::Todo]],
null: false,
deprecated: { reason: 'Use to-do items', milestone: '13.2' },
description: 'IDs of the updated to-do items.'
field :todos, [::Types::TodoType], field :todos, [::Types::TodoType],
null: false, null: false,
description: 'Updated to-do items.' description: 'Updated to-do items.'
...@@ -23,7 +17,6 @@ module Mutations ...@@ -23,7 +17,6 @@ module Mutations
updated_ids = mark_all_todos_done updated_ids = mark_all_todos_done
{ {
updated_ids: updated_ids,
todos: Todo.id_in(updated_ids), todos: Todo.id_in(updated_ids),
errors: [] errors: []
} }
......
...@@ -12,11 +12,6 @@ module Mutations ...@@ -12,11 +12,6 @@ module Mutations
required: true, required: true,
description: 'The global IDs of the to-do items to restore (a maximum of 50 is supported at once).' description: 'The global IDs of the to-do items to restore (a maximum of 50 is supported at once).'
field :updated_ids, [::Types::GlobalIDType[Todo]],
null: false,
description: 'The IDs of the updated to-do items.',
deprecated: { reason: 'Use to-do items', milestone: '13.2' }
field :todos, [::Types::TodoType], field :todos, [::Types::TodoType],
null: false, null: false,
description: 'Updated to-do items.' description: 'Updated to-do items.'
......
...@@ -5,15 +5,7 @@ module Types ...@@ -5,15 +5,7 @@ module Types
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
mount_aliased_mutation 'AddAwardEmoji', # placeholder for any FOSS mutations to be deprecated
Mutations::AwardEmojis::Add,
deprecated: { reason: 'Use awardEmojiAdd', milestone: '13.2' }
mount_aliased_mutation 'RemoveAwardEmoji',
Mutations::AwardEmojis::Remove,
deprecated: { reason: 'Use awardEmojiRemove', milestone: '13.2' }
mount_aliased_mutation 'ToggleAwardEmoji',
Mutations::AwardEmojis::Toggle,
deprecated: { reason: 'Use awardEmojiToggle', milestone: '13.2' }
end end
end end
end end
...@@ -61,12 +61,6 @@ module Types ...@@ -61,12 +61,6 @@ module Types
description: 'Raw URL of the snippet.', description: 'Raw URL of the snippet.',
null: false null: false
field :blob, type: Types::Snippets::BlobType,
description: 'Snippet blob.',
calls_gitaly: true,
null: false,
deprecated: { reason: 'Use `blobs`', milestone: '13.3' }
field :blobs, type: Types::Snippets::BlobType.connection_type, field :blobs, type: Types::Snippets::BlobType.connection_type,
description: 'Snippet blobs.', description: 'Snippet blobs.',
calls_gitaly: true, calls_gitaly: true,
......
This diff is collapsed.
...@@ -10,6 +10,32 @@ GraphQL is a versionless API, unlike the REST API. ...@@ -10,6 +10,32 @@ GraphQL is a versionless API, unlike the REST API.
Occasionally, items have to be updated or removed from the GraphQL API. Occasionally, items have to be updated or removed from the GraphQL API.
According to our [process for removing items](index.md#deprecation-and-removal-process), here are the items that have been removed. According to our [process for removing items](index.md#deprecation-and-removal-process), here are the items that have been removed.
## GitLab 14.0
Fields removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63293):
### GraphQL Mutations
| Argument name | Mutation | Deprecated in | Use instead |
| -------------------- | -------------------- | ------------- | -------------------------- |
| `updated_ids` | `todosMarkAllDone` | 13.2 | `todos` |
| `updated_ids` | `todoRestoreMany` | 13.2 | `todos` |
| `global_id` | `dastScannerProfileCreate`| 13.6 | `todos` |
| - | `addAwardEmoji` | 13.2 | `awardEmojiAdd` |
| - | `removeAwardEmoji` | 13.2 | `awardEmojiRemove` |
| - | `toggleAwardEmoji` | 13.2 | `ToggleAwardEmoji` |
| - | `runDastScan` | 13.5 | `dastOnDemandScanCreate` |
| - | `dismissVulnerability` | 13.5 | `vulnerabilityDismiss` |
| - | `revertVulnerabilityToDetected` | 13.5 | `vulnerabilityRevertToDetected` |
### GraphQL Types
| Field name | GraphQL type | Deprecated in | Use instead |
| -------------------- | -------------------- | ------------- | -------------------------- |
| `blob` | `SnippetType` | 13.3 | `blobs` |
| `global_id` | `DastScannerProfileType` | 13.6 | `blobs` |
| `vulnerabilities_count_by_day_and_severity` | `GroupType`, `QueryType` | 13.3 | None. Plaintext tokens no longer supported for security reasons. |
## GitLab 13.6 ## GitLab 13.6
Fields removed in [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44866): Fields removed in [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44866):
......
mutation runDastScan(
$projectPath: ID!
$targetUrl: String!
$branch: String!
$scanType: DastScanTypeEnum!
) {
runDastScan(
input: {
projectPath: $projectPath
targetUrl: $targetUrl
branch: $branch
scanType: $scanType
}
) {
pipelineUrl
errors
}
}
...@@ -6,15 +6,6 @@ module EE ...@@ -6,15 +6,6 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
mount_mutation ::Mutations::Pipelines::RunDastScan,
deprecated: { reason: 'Use DastOnDemandScanCreate', milestone: '13.4' }
mount_aliased_mutation 'DismissVulnerability', ::Mutations::Vulnerabilities::Dismiss,
deprecated: { reason: 'Use vulnerabilityDismiss', milestone: '13.5' }
mount_aliased_mutation 'RevertVulnerabilityToDetected', ::Mutations::Vulnerabilities::RevertToDetected,
deprecated: { reason: 'Use vulnerabilityRevertToDetected', milestone: '13.5' }
mount_aliased_mutation 'CreateIteration', ::Mutations::Iterations::Create, mount_aliased_mutation 'CreateIteration', ::Mutations::Iterations::Create,
deprecated: { reason: 'Use iterationCreate', milestone: '14.0' } deprecated: { reason: 'Use iterationCreate', milestone: '14.0' }
end end
......
...@@ -65,13 +65,6 @@ module EE ...@@ -65,13 +65,6 @@ module EE
description: 'Number of vulnerabilities per day for the projects in the group and its subgroups.', description: 'Number of vulnerabilities per day for the projects in the group and its subgroups.',
resolver: ::Resolvers::VulnerabilitiesCountPerDayResolver resolver: ::Resolvers::VulnerabilitiesCountPerDayResolver
field :vulnerabilities_count_by_day_and_severity,
::Types::VulnerabilitiesCountByDayAndSeverityType.connection_type,
null: true,
description: 'Number of vulnerabilities per severity level, per day, for the projects in the group and its subgroups.',
resolver: ::Resolvers::VulnerabilitiesHistoryResolver,
deprecated: { reason: 'Use `vulnerabilitiesCountByDay`', milestone: '13.3' }
field :vulnerability_grades, field :vulnerability_grades,
[::Types::VulnerableProjectsByGradeType], [::Types::VulnerableProjectsByGradeType],
null: false, null: false,
......
...@@ -37,16 +37,6 @@ module EE ...@@ -37,16 +37,6 @@ module EE
Number of vulnerabilities per day for the projects on the current user's instance security dashboard. Number of vulnerabilities per day for the projects on the current user's instance security dashboard.
DESC DESC
field :vulnerabilities_count_by_day_and_severity,
::Types::VulnerabilitiesCountByDayAndSeverityType.connection_type,
null: true,
resolver: ::Resolvers::VulnerabilitiesHistoryResolver,
deprecated: { reason: :discouraged, replacement: 'Query.vulnerabilitiesCountByDay', milestone: '13.3' },
description: <<~DESC
Number of vulnerabilities per severity level, per day, for the projects on the
current user's instance security dashboard.
DESC
field :geo_node, ::Types::Geo::GeoNodeType, field :geo_node, ::Types::Geo::GeoNodeType,
null: true, null: true,
resolver: ::Resolvers::Geo::GeoNodeResolver, resolver: ::Resolvers::Geo::GeoNodeResolver,
......
...@@ -11,11 +11,6 @@ module Mutations ...@@ -11,11 +11,6 @@ module Mutations
null: true, null: true,
description: 'ID of the scanner profile.' description: 'ID of the scanner profile.'
field :global_id, ::Types::GlobalIDType[::DastScannerProfile],
null: true,
description: 'ID of the scanner profile.',
deprecated: { reason: 'Use `id`', milestone: '13.6' }
argument :full_path, GraphQL::ID_TYPE, argument :full_path, GraphQL::ID_TYPE,
required: true, required: true,
description: 'The project the scanner profile belongs to.' description: 'The project the scanner profile belongs to.'
......
# frozen_string_literal: true
module Mutations
module Pipelines
class RunDastScan < BaseMutation
include FindsProject
graphql_name 'RunDASTScan'
field :pipeline_url, GraphQL::STRING_TYPE,
null: true,
description: 'URL of the pipeline that was created.'
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'The project the DAST scan belongs to.'
argument :target_url, GraphQL::STRING_TYPE,
required: true,
description: 'The URL of the target to be scanned.'
argument :branch, GraphQL::STRING_TYPE,
required: true,
description: 'The branch to be associated with the scan.'
argument :scan_type, Types::DastScanTypeEnum,
required: true,
description: 'The type of scan to be run.'
authorize :create_on_demand_dast_scan
def resolve(project_path:, target_url:, branch:, scan_type:)
project = authorized_find!(project_path)
result = ::DastOnDemandScans::CreateService.new(
container: project,
current_user: current_user,
params: {
branch: branch,
dast_site_profile: DastSiteProfile.new(dast_site: DastSite.new(url: target_url))
}
).execute
if result.success?
success_response(project: project, pipeline: result.payload[:pipeline])
else
error_response(result.message)
end
end
private
def success_response(project:, pipeline:)
pipeline_url = Rails.application.routes.url_helpers.project_pipeline_url(
project,
pipeline
)
{
errors: [],
pipeline_url: pipeline_url
}
end
def error_response(message)
{ errors: [message] }
end
end
end
end
# frozen_string_literal: true
module Resolvers
class VulnerabilitiesHistoryResolver < VulnerabilitiesBaseResolver
include Gitlab::Utils::StrongMemoize
MAX_DAYS = ::Vulnerability::MAX_DAYS_OF_HISTORY
type Types::VulnerabilitiesCountByDayAndSeverityType, null: true
argument :start_date, GraphQL::Types::ISO8601Date, required: true,
description: 'First day for which to fetch vulnerability history.'
argument :end_date, GraphQL::Types::ISO8601Date, required: true,
description: 'Last day for which to fetch vulnerability history.'
def resolve(**args)
return [] unless vulnerable
start_date = args[:start_date]
end_date = args[:end_date]
days = end_date - start_date + 1
if days > MAX_DAYS
raise ::Vulnerability::TooManyDaysError, "Cannot fetch counts for more than #{MAX_DAYS} days"
else
vulnerable.vulnerabilities.counts_by_day_and_severity(start_date, end_date).to_a
end
end
end
end
...@@ -10,11 +10,6 @@ module Types ...@@ -10,11 +10,6 @@ module Types
field :id, ::Types::GlobalIDType[::DastScannerProfile], null: false, field :id, ::Types::GlobalIDType[::DastScannerProfile], null: false,
description: 'ID of the DAST scanner profile.' description: 'ID of the DAST scanner profile.'
field :global_id, ::Types::GlobalIDType[::DastScannerProfile], null: false,
description: 'ID of the DAST scanner profile.',
deprecated: { reason: 'Use `id`', milestone: '13.6' },
method: :id
field :profile_name, GraphQL::STRING_TYPE, null: true, field :profile_name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the DAST scanner profile.', description: 'Name of the DAST scanner profile.',
method: :name method: :name
......
# frozen_string_literal: true
module Types
# rubocop: disable Graphql/AuthorizeTypes
class VulnerabilitiesCountByDayAndSeverityType < BaseObject
graphql_name 'VulnerabilitiesCountByDayAndSeverity'
description 'Represents the number of vulnerabilities for a particular severity on a particular day. This data is retained for 365 days'
field :count, GraphQL::INT_TYPE, null: true,
description: 'Number of vulnerabilities.'
field :day, GraphQL::Types::ISO8601Date, null: true,
description: 'Date for the count.'
field :severity, VulnerabilitySeverityEnum, null: true,
description: 'Severity of the counted vulnerabilities.'
end
end
...@@ -16,7 +16,7 @@ RSpec.describe GitlabSchema.types['Group'] do ...@@ -16,7 +16,7 @@ RSpec.describe GitlabSchema.types['Group'] do
it { expect(described_class).to have_graphql_field(:timelogs, complexity: 5) } it { expect(described_class).to have_graphql_field(:timelogs, complexity: 5) }
it { expect(described_class).to have_graphql_field(:vulnerabilities) } it { expect(described_class).to have_graphql_field(:vulnerabilities) }
it { expect(described_class).to have_graphql_field(:vulnerability_scanners) } it { expect(described_class).to have_graphql_field(:vulnerability_scanners) }
it { expect(described_class).to have_graphql_field(:vulnerabilities_count_by_day_and_severity) } it { expect(described_class).to have_graphql_field(:vulnerabilities_count_by_day) }
it { expect(described_class).to have_graphql_field(:vulnerability_grades) } it { expect(described_class).to have_graphql_field(:vulnerability_grades) }
it { expect(described_class).to have_graphql_field(:code_coverage_activities) } it { expect(described_class).to have_graphql_field(:code_coverage_activities) }
it { expect(described_class).to have_graphql_field(:stats) } it { expect(described_class).to have_graphql_field(:stats) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::Pipelines::RunDastScan do
let(:group) { create(:group) }
let(:project) { create(:project, :repository, group: group) }
let(:user) { create(:user) }
let(:project_path) { project.full_path }
let(:target_url) { generate(:url) }
let(:branch) { project.default_branch }
let(:scan_type) { Types::DastScanTypeEnum.enum[:passive] }
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
before do
stub_licensed_features(security_on_demand_scans: true)
end
describe '#resolve' do
subject do
mutation.resolve(
branch: branch,
project_path: project_path,
target_url: target_url,
scan_type: scan_type
)
end
context 'when on demand scan feature is not enabled' do
it 'raises an exception' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when on demand scan feature is enabled' do
context 'when the project does not exist' do
let(:project_path) { SecureRandom.hex }
it 'raises an exception' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when the user is not associated with the project' do
it 'raises an exception' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when the user is an owner' do
it 'has no errors' do
group.add_owner(user)
expect(subject[:errors]).to be_empty
end
end
context 'when the user is a maintainer' do
it 'has no errors' do
project.add_maintainer(user)
expect(subject[:errors]).to be_empty
end
end
context 'when the user is a developer' do
it 'has no errors' do
project.add_developer(user)
expect(subject[:errors]).to be_empty
end
end
context 'when the user can run a dast scan' do
it 'returns a pipeline_url containing the correct path' do
project.add_developer(user)
actual_url = subject[:pipeline_url]
pipeline = Ci::Pipeline.last
expected_url = Rails.application.routes.url_helpers.project_pipeline_url(
project,
pipeline
)
expect(actual_url).to eq(expected_url)
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::VulnerabilitiesHistoryResolver do
include GraphqlHelpers
subject { resolve(described_class, obj: group, args: args, ctx: { current_user: user }) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:user) { create(:user) }
describe '#resolve' do
let(:args) { { start_date: Date.parse('2019-10-15'), end_date: Date.parse('2019-10-21') } }
it "fetches historical vulnerability data from the start date to the end date" do
travel_to(Date.parse('2019-10-31')) do
create(:vulnerability, :critical, created_at: 15.days.ago, dismissed_at: 10.days.ago, project: project)
create(:vulnerability, :high, created_at: 15.days.ago, dismissed_at: 11.days.ago, project: project)
create(:vulnerability, :critical, created_at: 14.days.ago, resolved_at: 12.days.ago, project: project)
ordered_history = subject.sort_by { |count| [count['day'], count['severity']] }
expect(ordered_history.to_json).to eq([
{ 'day' => '2019-10-16', 'severity' => 'critical', 'count' => 1, 'id' => nil },
{ 'day' => '2019-10-16', 'severity' => 'high', 'count' => 1, 'id' => nil },
{ 'day' => '2019-10-17', 'severity' => 'critical', 'count' => 2, 'id' => nil },
{ 'day' => '2019-10-17', 'severity' => 'high', 'count' => 1, 'id' => nil },
{ 'day' => '2019-10-18', 'severity' => 'critical', 'count' => 2, 'id' => nil },
{ 'day' => '2019-10-18', 'severity' => 'high', 'count' => 1, 'id' => nil },
{ 'day' => '2019-10-19', 'severity' => 'critical', 'count' => 1, 'id' => nil },
{ 'day' => '2019-10-19', 'severity' => 'high', 'count' => 1, 'id' => nil },
{ 'day' => '2019-10-20', 'severity' => 'critical', 'count' => 1, 'id' => nil }
].to_json)
end
end
context 'when given more than 10 days' do
let(:args) { { start_date: Date.parse('2019-10-11'), end_date: Date.parse('2019-10-21') } }
it 'raises an error stating that no more than 10 days can be requested' do
expect { subject }.to raise_error(::Vulnerability::TooManyDaysError, 'Cannot fetch counts for more than 10 days')
end
end
end
end
...@@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['DastScannerProfile'] do ...@@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['DastScannerProfile'] do
let_it_be(:dast_scanner_profile) { create(:dast_scanner_profile) } let_it_be(:dast_scanner_profile) { create(:dast_scanner_profile) }
let_it_be(:project) { dast_scanner_profile.project } let_it_be(:project) { dast_scanner_profile.project }
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:fields) { %i[id globalId profileName spiderTimeout targetTimeout editPath scanType useAjaxSpider showDebugMessages referencedInSecurityPolicies] } let_it_be(:fields) { %i[id profileName spiderTimeout targetTimeout editPath scanType useAjaxSpider showDebugMessages referencedInSecurityPolicies] }
let(:response) do let(:response) do
GitlabSchema.execute( GitlabSchema.execute(
...@@ -45,7 +45,6 @@ RSpec.describe GitlabSchema.types['DastScannerProfile'] do ...@@ -45,7 +45,6 @@ RSpec.describe GitlabSchema.types['DastScannerProfile'] do
dastScannerProfiles { dastScannerProfiles {
nodes { nodes {
id id
globalId
profileName profileName
targetTimeout targetTimeout
spiderTimeout spiderTimeout
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['Mutation'] do
describe 'deprecated mutations' do
using RSpec::Parameterized::TableSyntax
where(:field_name, :reason, :milestone) do
'RunDastScan' | 'Use DastOnDemandScanCreate' | '13.4'
end
with_them do
let(:field) { get_field(field_name) }
let(:deprecation_reason) { "#{reason}. Deprecated in #{milestone}." }
it { expect(field).to be_present }
it { expect(field.deprecation_reason).to eq(deprecation_reason) }
end
end
describe 'aliased deprecated mutations' do
using RSpec::Parameterized::TableSyntax
where(:alias_name, :canonical_name) do
'DismissVulnerability' | 'VulnerabilityDismiss'
'RevertVulnerabilityToDetected' | 'VulnerabilityRevertToDetected'
end
with_them do
let(:alias_field) { get_field(alias_name) }
let(:canonical_field) { get_field(canonical_name) }
it { expect(alias_field).to be_present }
it { expect(canonical_field).to be_present }
it { expect(alias_field.deprecation_reason).to be_present }
it { expect(canonical_field.deprecation_reason).not_to be_present }
it { expect(alias_field.resolver.fields).to eq(canonical_field.resolver.fields) }
it { expect(alias_field.resolver.arguments).to eq(canonical_field.resolver.arguments) }
end
end
def get_field(name)
described_class.fields[GraphqlHelpers.fieldnamerize(name.camelize)]
end
end
...@@ -10,7 +10,7 @@ RSpec.describe GitlabSchema.types['Query'] do ...@@ -10,7 +10,7 @@ RSpec.describe GitlabSchema.types['Query'] do
:vulnerabilities, :vulnerabilities,
:vulnerability, :vulnerability,
:instance_security_dashboard, :instance_security_dashboard,
:vulnerabilities_count_by_day_and_severity, :vulnerabilities_count_by_day,
:current_license, :current_license,
:license_history_entries :license_history_entries
).at_least ).at_least
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilitiesCountByDayAndSeverity'] do
it { expect(described_class).to have_graphql_fields(:count, :day, :severity) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'group(fullPath).vulnerabilitiesCountByDayAndSeverity' do
include GraphqlHelpers
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:current_user) { create(:user) }
let(:query) { graphql_query_for(:group, { fullPath: group.full_path }, history_field) }
let(:query_result) { graphql_data.dig('group', 'vulnerabilitiesCountByDayAndSeverity', 'nodes') }
let(:history_field) do
query_graphql_field(
:vulnerabilitiesCountByDayAndSeverity,
{
start_date: Date.parse('2019-10-15').iso8601,
end_date: Date.parse('2019-10-21').iso8601
},
history_fields
)
end
let(:history_fields) do
query_graphql_field(:nodes, nil, <<~FIELDS)
count
day
severity
FIELDS
end
it "fetches historical vulnerability data from the start date to the end date for projects in the group and its subgroups" do
travel_to(Time.zone.parse('2019-10-31')) do
project.add_developer(current_user)
create(:vulnerability, :critical, created_at: 15.days.ago, dismissed_at: 10.days.ago, project: project)
create(:vulnerability, :high, created_at: 15.days.ago, dismissed_at: 11.days.ago, project: project)
create(:vulnerability, :critical, created_at: 14.days.ago, resolved_at: 12.days.ago, project: project)
post_graphql(query, current_user: current_user)
ordered_history = query_result.sort_by { |count| [count['day'], count['severity']] }
expect(ordered_history).to eq([
{ 'severity' => 'CRITICAL', 'day' => '2019-10-16', 'count' => 1 },
{ 'severity' => 'HIGH', 'day' => '2019-10-16', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-17', 'count' => 2 },
{ 'severity' => 'HIGH', 'day' => '2019-10-17', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-18', 'count' => 2 },
{ 'severity' => 'HIGH', 'day' => '2019-10-18', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-19', 'count' => 1 },
{ 'severity' => 'HIGH', 'day' => '2019-10-19', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-20', 'count' => 1 }
])
end
end
end
...@@ -25,12 +25,6 @@ RSpec.describe 'Creating a DAST Scanner Profile' do ...@@ -25,12 +25,6 @@ RSpec.describe 'Creating a DAST Scanner Profile' do
expect(mutation_response['id']).to eq(dast_scanner_profile.to_global_id.to_s) expect(mutation_response['id']).to eq(dast_scanner_profile.to_global_id.to_s)
end end
it 'returns the dast_scanner_profile global_id' do
post_graphql_mutation(mutation, current_user: current_user)
expect(mutation_response['globalId']).to eq(dast_scanner_profile.to_global_id.to_s)
end
it 'sets default values of omitted properties' do it 'sets default values of omitted properties' do
post_graphql_mutation(mutation, current_user: current_user) post_graphql_mutation(mutation, current_user: current_user)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Running a DAST Scan' do
include GraphqlHelpers
let(:project) { create(:project, :repository, creator: current_user) }
let(:current_user) { create(:user) }
let(:project_path) { project.full_path }
let(:target_url) { generate(:url) }
let(:branch) { project.default_branch }
let(:scan_type) { Types::DastScanTypeEnum.enum[:passive].upcase }
let(:mutation) do
graphql_mutation(
:run_dast_scan,
branch: branch,
project_path: project_path,
target_url: target_url,
scan_type: scan_type
)
end
def mutation_response
graphql_mutation_response(:run_dast_scan)
end
before do
stub_licensed_features(security_on_demand_scans: true)
end
context 'when on demand scan feature is not enabled' do
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not ' \
'exist or you don\'t have permission to perform this action']
end
context 'when on demand scan feature is enabled' do
context 'when the user does not have permission to run a dast scan' do
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not ' \
'exist or you don\'t have permission to perform this action']
end
context 'when the user can run a dast scan' do
before do
project.add_developer(current_user)
end
it 'returns a pipeline_url containing the correct path' do
post_graphql_mutation(mutation, current_user: current_user)
pipeline = Ci::Pipeline.last
expected_url = Rails.application.routes.url_helpers.project_pipeline_url(
project,
pipeline
)
expect(mutation_response['pipelineUrl']).to eq(expected_url)
end
context 'when pipeline creation fails' do
before do
allow_any_instance_of(Ci::Pipeline).to receive(:created_successfully?).and_return(false)
allow_any_instance_of(Ci::Pipeline).to receive(:full_error_messages).and_return('error message')
end
it_behaves_like 'a mutation that returns errors in the response', errors: ['error message']
end
end
end
end
...@@ -87,11 +87,5 @@ RSpec.describe 'Query.project(fullPath).dastScannerProfiles' do ...@@ -87,11 +87,5 @@ RSpec.describe 'Query.project(fullPath).dastScannerProfiles' do
it { is_expected.to eq(dast_scanner_profile.to_global_id.to_s) } it { is_expected.to eq(dast_scanner_profile.to_global_id.to_s) }
end end
describe 'first dast scanner profile globalId' do
subject { response_data.dig('project', 'dastScannerProfiles', 'nodes').first['globalId'] }
it { is_expected.to eq(dast_scanner_profile.to_global_id.to_s) }
end
end end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Query' do
include GraphqlHelpers
describe '.vulnerabilitiesCountByDayAndSeverity' do
let(:query_result) { graphql_data.dig('vulnerabilitiesCountByDayAndSeverity', 'nodes') }
let(:query) do
graphql_query_for(
:vulnerabilitiesCountByDayAndSeverity,
{
start_date: Date.parse('2019-10-15').iso8601,
end_date: Date.parse('2019-10-21').iso8601
},
history_fields
)
end
let(:history_fields) do
query_graphql_field(:nodes, nil, <<~FIELDS)
count
day
severity
FIELDS
end
it "fetches historical vulnerability data from the start date to the end date for projects on the current user's instance security dashboard" do
travel_to(Time.zone.parse('2019-10-31')) do
project = create(:project)
current_user = create(:user)
current_user.security_dashboard_projects << project
project.add_developer(current_user)
create(:vulnerability, :critical, created_at: 15.days.ago, dismissed_at: 10.days.ago, project: project)
create(:vulnerability, :high, created_at: 15.days.ago, dismissed_at: 11.days.ago, project: project)
create(:vulnerability, :critical, created_at: 14.days.ago, resolved_at: 12.days.ago, project: project)
post_graphql(query, current_user: current_user)
ordered_history = query_result.sort_by { |count| [count['day'], count['severity']] }
expect(ordered_history).to eq([
{ 'severity' => 'CRITICAL', 'day' => '2019-10-16', 'count' => 1 },
{ 'severity' => 'HIGH', 'day' => '2019-10-16', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-17', 'count' => 2 },
{ 'severity' => 'HIGH', 'day' => '2019-10-17', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-18', 'count' => 2 },
{ 'severity' => 'HIGH', 'day' => '2019-10-18', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-19', 'count' => 1 },
{ 'severity' => 'HIGH', 'day' => '2019-10-19', 'count' => 1 },
{ 'severity' => 'CRITICAL', 'day' => '2019-10-20', 'count' => 1 }
])
end
end
end
end
...@@ -21,26 +21,25 @@ RSpec.describe Mutations::Todos::MarkAllDone do ...@@ -21,26 +21,25 @@ RSpec.describe Mutations::Todos::MarkAllDone do
describe '#resolve' do describe '#resolve' do
it 'marks all pending todos as done' do it 'marks all pending todos as done' do
updated_todo_ids, todos = mutation_for(current_user).resolve.values_at(:updated_ids, :todos) todos = mutation_for(current_user).resolve[:todos]
expect(todo1.reload.state).to eq('done') expect(todo1.reload.state).to eq('done')
expect(todo2.reload.state).to eq('done') expect(todo2.reload.state).to eq('done')
expect(todo3.reload.state).to eq('done') expect(todo3.reload.state).to eq('done')
expect(other_user_todo.reload.state).to eq('pending') expect(other_user_todo.reload.state).to eq('pending')
expect(updated_todo_ids).to contain_exactly(todo1.id, todo3.id)
expect(todos).to contain_exactly(todo1, todo3) expect(todos).to contain_exactly(todo1, todo3)
end end
it 'behaves as expected if there are no todos for the requesting user' do it 'behaves as expected if there are no todos for the requesting user' do
updated_todo_ids = mutation_for(user3).resolve.dig(:updated_ids) todos = mutation_for(user3).resolve[:todos]
expect(todo1.reload.state).to eq('pending') expect(todo1.reload.state).to eq('pending')
expect(todo2.reload.state).to eq('done') expect(todo2.reload.state).to eq('done')
expect(todo3.reload.state).to eq('pending') expect(todo3.reload.state).to eq('pending')
expect(other_user_todo.reload.state).to eq('pending') expect(other_user_todo.reload.state).to eq('pending')
expect(updated_todo_ids).to be_empty expect(todos).to be_empty
end end
context 'when user is not logged in' do context 'when user is not logged in' do
......
...@@ -15,28 +15,6 @@ RSpec.describe Types::MutationType do ...@@ -15,28 +15,6 @@ RSpec.describe Types::MutationType do
expect(described_class).to have_graphql_mutation(Mutations::MergeRequests::SetDraft) expect(described_class).to have_graphql_mutation(Mutations::MergeRequests::SetDraft)
end end
describe 'deprecated and aliased mutations' do
using RSpec::Parameterized::TableSyntax
where(:alias_name, :canonical_name) do
'AddAwardEmoji' | 'AwardEmojiAdd'
'RemoveAwardEmoji' | 'AwardEmojiRemove'
'ToggleAwardEmoji' | 'AwardEmojiToggle'
end
with_them do
let(:alias_field) { get_field(alias_name) }
let(:canonical_field) { get_field(canonical_name) }
it { expect(alias_field).to be_present }
it { expect(canonical_field).to be_present }
it { expect(alias_field.deprecation_reason).to be_present }
it { expect(canonical_field.deprecation_reason).not_to be_present }
it { expect(alias_field.resolver.fields).to eq(canonical_field.resolver.fields) }
it { expect(alias_field.resolver.arguments).to eq(canonical_field.resolver.arguments) }
end
end
def get_field(name) def get_field(name)
described_class.fields[GraphqlHelpers.fieldnamerize(name)] described_class.fields[GraphqlHelpers.fieldnamerize(name)]
end end
......
...@@ -13,7 +13,7 @@ RSpec.describe GitlabSchema.types['Snippet'] do ...@@ -13,7 +13,7 @@ RSpec.describe GitlabSchema.types['Snippet'] do
:visibility_level, :created_at, :updated_at, :visibility_level, :created_at, :updated_at,
:web_url, :raw_url, :ssh_url_to_repo, :http_url_to_repo, :web_url, :raw_url, :ssh_url_to_repo, :http_url_to_repo,
:notes, :discussions, :user_permissions, :notes, :discussions, :user_permissions,
:description_html, :blob, :blobs] :description_html, :blobs]
expect(described_class).to have_graphql_fields(*expected_fields) expect(described_class).to have_graphql_fields(*expected_fields)
end end
...@@ -133,32 +133,6 @@ RSpec.describe GitlabSchema.types['Snippet'] do ...@@ -133,32 +133,6 @@ RSpec.describe GitlabSchema.types['Snippet'] do
end end
end end
describe '#blob' do
let(:query_blob) { subject.dig('data', 'snippets', 'nodes')[0]['blob'] }
subject { GitlabSchema.execute(snippet_query_for(field: 'blob'), context: { current_user: user }).as_json }
context 'when snippet has repository' do
let!(:snippet) { create(:personal_snippet, :repository, :public, author: user) }
let(:blob) { snippet.blobs.first }
it 'returns the first blob from the repository' do
expect(query_blob['name']).to eq blob.name
expect(query_blob['path']).to eq blob.path
end
end
context 'when snippet does not have a repository' do
let!(:snippet) { create(:personal_snippet, :public, author: user) }
let(:blob) { snippet.blob }
it 'returns SnippetBlob type' do
expect(query_blob['name']).to eq blob.name
expect(query_blob['path']).to eq blob.path
end
end
end
describe '#blobs' do describe '#blobs' do
let_it_be(:snippet) { create(:personal_snippet, :public, author: user) } let_it_be(:snippet) { create(:personal_snippet, :public, author: user) }
......
...@@ -31,7 +31,7 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do ...@@ -31,7 +31,7 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do
end end
it 'returns false' do it 'returns false' do
snippet_blob = subject.dig('data', 'snippets', 'edges')[0].dig('node', 'blob') snippet_blob = subject.dig('data', 'snippets', 'edges').first.dig('node', 'blobs', 'nodes').find { |b| b['path'] == blob.path }
expect(snippet_blob['path']).to eq blob.path expect(snippet_blob['path']).to eq blob.path
expect(blob_attribute).to be_nil expect(blob_attribute).to be_nil
...@@ -47,10 +47,12 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do ...@@ -47,10 +47,12 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do
snippets(ids: "#{snippet.to_global_id}") { snippets(ids: "#{snippet.to_global_id}") {
edges { edges {
node { node {
blob { blobs {
path nodes {
simpleViewer { path
collapsed simpleViewer {
collapsed
}
} }
} }
} }
...@@ -73,10 +75,12 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do ...@@ -73,10 +75,12 @@ RSpec.describe GitlabSchema.types['SnippetBlobViewer'] do
snippets(ids: "#{snippet.to_global_id}") { snippets(ids: "#{snippet.to_global_id}") {
edges { edges {
node { node {
blob { blobs {
path nodes {
simpleViewer { path
tooLarge simpleViewer {
tooLarge
}
} }
} }
} }
......
...@@ -22,8 +22,8 @@ RSpec.describe 'Marking all todos done' do ...@@ -22,8 +22,8 @@ RSpec.describe 'Marking all todos done' do
graphql_mutation(:todos_mark_all_done, input, graphql_mutation(:todos_mark_all_done, input,
<<-QL.strip_heredoc <<-QL.strip_heredoc
clientMutationId clientMutationId
todos { id }
errors errors
updatedIds
QL QL
) )
end end
...@@ -40,7 +40,7 @@ RSpec.describe 'Marking all todos done' do ...@@ -40,7 +40,7 @@ RSpec.describe 'Marking all todos done' do
expect(todo3.reload.state).to eq('done') expect(todo3.reload.state).to eq('done')
expect(other_user_todo.reload.state).to eq('pending') expect(other_user_todo.reload.state).to eq('pending')
updated_todo_ids = mutation_response['updatedIds'] updated_todo_ids = mutation_response['todos'].map { |todo| todo['id'] }
expect(updated_todo_ids).to contain_exactly(global_id_of(todo1), global_id_of(todo3)) expect(updated_todo_ids).to contain_exactly(global_id_of(todo1), global_id_of(todo3))
end end
...@@ -52,7 +52,7 @@ RSpec.describe 'Marking all todos done' do ...@@ -52,7 +52,7 @@ RSpec.describe 'Marking all todos done' do
expect(todo3.reload.state).to eq('pending') expect(todo3.reload.state).to eq('pending')
expect(other_user_todo.reload.state).to eq('pending') expect(other_user_todo.reload.state).to eq('pending')
updated_todo_ids = mutation_response['updatedIds'] updated_todo_ids = mutation_response['todos']
expect(updated_todo_ids).to be_empty expect(updated_todo_ids).to be_empty
end end
......
...@@ -22,7 +22,6 @@ RSpec.describe 'Restoring many Todos' do ...@@ -22,7 +22,6 @@ RSpec.describe 'Restoring many Todos' do
<<-QL.strip_heredoc <<-QL.strip_heredoc
clientMutationId clientMutationId
errors errors
updatedIds
todos { todos {
id id
state state
...@@ -44,7 +43,6 @@ RSpec.describe 'Restoring many Todos' do ...@@ -44,7 +43,6 @@ RSpec.describe 'Restoring many Todos' do
expect(mutation_response).to include( expect(mutation_response).to include(
'errors' => be_empty, 'errors' => be_empty,
'updatedIds' => match_array(input_ids),
'todos' => contain_exactly( 'todos' => contain_exactly(
{ 'id' => global_id_of(todo1), 'state' => 'pending' }, { 'id' => global_id_of(todo1), 'state' => 'pending' },
{ 'id' => global_id_of(todo2), 'state' => 'pending' } { 'id' => global_id_of(todo2), 'state' => 'pending' }
......
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