Commit cc6daea3 authored by James Lopez's avatar James Lopez

Merge branch '290761-add-details-to-vulnerability-graphql' into 'master'

Add details to Vulnerability GraphQL

See merge request gitlab-org/gitlab!49465
parents 151965b1 33cc752c
......@@ -26512,6 +26512,11 @@ type Vulnerability implements Noteable {
"""
description: String
"""
Details of the vulnerability
"""
details: [VulnerabilityDetail!]!
"""
Timestamp of when the vulnerability was first detected
"""
......@@ -26780,6 +26785,366 @@ type VulnerabilityConnection {
pageInfo: PageInfo!
}
"""
Represents a vulnerability detail field. The fields with data will depend on the vulnerability detail type
"""
union VulnerabilityDetail = VulnerabilityDetailBase | VulnerabilityDetailBoolean | VulnerabilityDetailCode | VulnerabilityDetailCommit | VulnerabilityDetailDiff | VulnerabilityDetailFileLocation | VulnerabilityDetailInt | VulnerabilityDetailList | VulnerabilityDetailMarkdown | VulnerabilityDetailModuleLocation | VulnerabilityDetailTable | VulnerabilityDetailText | VulnerabilityDetailUrl
"""
Represents the vulnerability details base
"""
type VulnerabilityDetailBase {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Name of the field.
"""
name: String!
}
"""
Represents the vulnerability details boolean value
"""
type VulnerabilityDetailBoolean {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Name of the field.
"""
name: String!
"""
Value of the field.
"""
value: Boolean!
}
"""
Represents the vulnerability details code field
"""
type VulnerabilityDetailCode {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Language of the code.
"""
lang: String
"""
Name of the field.
"""
name: String!
"""
Source code.
"""
value: String!
}
"""
Represents the vulnerability details commit field
"""
type VulnerabilityDetailCommit {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Name of the field.
"""
name: String!
"""
The commit SHA value.
"""
value: String!
}
"""
Represents the vulnerability details diff field
"""
type VulnerabilityDetailDiff {
"""
Value of the field after the change.
"""
after: String!
"""
Value of the field before the change.
"""
before: String!
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Name of the field.
"""
name: String!
}
"""
Represents the vulnerability details location within a file in the project
"""
type VulnerabilityDetailFileLocation {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
File name.
"""
fileName: String!
"""
End line number of the file location.
"""
lineEnd: Int!
"""
Start line number of the file location.
"""
lineStart: Int!
"""
Name of the field.
"""
name: String!
}
"""
Represents the vulnerability details integer value
"""
type VulnerabilityDetailInt {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Name of the field.
"""
name: String!
"""
Value of the field.
"""
value: Int!
}
"""
Represents the vulnerability details list value
"""
type VulnerabilityDetailList {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
List of details.
"""
items: [VulnerabilityDetail!]!
"""
Name of the field.
"""
name: String!
}
"""
Represents the vulnerability details Markdown field
"""
type VulnerabilityDetailMarkdown {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Name of the field.
"""
name: String!
"""
Value of the Markdown field.
"""
value: String!
}
"""
Represents the vulnerability details location within a file in the project
"""
type VulnerabilityDetailModuleLocation {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Module name.
"""
moduleName: String!
"""
Name of the field.
"""
name: String!
"""
Offset of the module location.
"""
offset: Int!
}
"""
Represents the vulnerability details table value
"""
type VulnerabilityDetailTable {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Table headers.
"""
headers: [VulnerabilityDetail!]!
"""
Name of the field.
"""
name: String!
"""
Table rows.
"""
rows: [VulnerabilityDetail!]!
}
"""
Represents the vulnerability details text field
"""
type VulnerabilityDetailText {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Name of the field.
"""
name: String!
"""
Value of the text field.
"""
value: String!
}
"""
Represents the vulnerability details URL field
"""
type VulnerabilityDetailUrl {
"""
Description of the field.
"""
description: String!
"""
Name of the field.
"""
fieldName: String
"""
Href of the URL.
"""
href: String!
"""
Name of the field.
"""
name: String!
"""
Text of the URL.
"""
text: String
}
"""
Autogenerated input type of VulnerabilityDismiss
"""
......
......@@ -3937,6 +3937,7 @@ Represents a vulnerability.
| `confirmedAt` | Time | Timestamp of when the vulnerability state was changed to confirmed |
| `confirmedBy` | User | The user that confirmed the vulnerability. |
| `description` | String | Description of the vulnerability |
| `details` | VulnerabilityDetail! => Array | Details of the vulnerability |
| `detectedAt` | Time! | Timestamp of when the vulnerability was first detected |
| `discussions` | DiscussionConnection! | All discussions on this noteable |
| `dismissedAt` | Time | Timestamp of when the vulnerability state was changed to dismissed |
......@@ -3973,6 +3974,155 @@ Autogenerated return type of VulnerabilityConfirm.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `vulnerability` | Vulnerability | The vulnerability after state change. |
### VulnerabilityDetailBase
Represents the vulnerability details base.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `name` | String! | Name of the field. |
### VulnerabilityDetailBoolean
Represents the vulnerability details boolean value.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `name` | String! | Name of the field. |
| `value` | Boolean! | Value of the field. |
### VulnerabilityDetailCode
Represents the vulnerability details code field.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `lang` | String | Language of the code. |
| `name` | String! | Name of the field. |
| `value` | String! | Source code. |
### VulnerabilityDetailCommit
Represents the vulnerability details commit field.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `name` | String! | Name of the field. |
| `value` | String! | The commit SHA value. |
### VulnerabilityDetailDiff
Represents the vulnerability details diff field.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `after` | String! | Value of the field after the change. |
| `before` | String! | Value of the field before the change. |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `name` | String! | Name of the field. |
### VulnerabilityDetailFileLocation
Represents the vulnerability details location within a file in the project.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `fileName` | String! | File name. |
| `lineEnd` | Int! | End line number of the file location. |
| `lineStart` | Int! | Start line number of the file location. |
| `name` | String! | Name of the field. |
### VulnerabilityDetailInt
Represents the vulnerability details integer value.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `name` | String! | Name of the field. |
| `value` | Int! | Value of the field. |
### VulnerabilityDetailList
Represents the vulnerability details list value.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `items` | VulnerabilityDetail! => Array | List of details. |
| `name` | String! | Name of the field. |
### VulnerabilityDetailMarkdown
Represents the vulnerability details Markdown field.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `name` | String! | Name of the field. |
| `value` | String! | Value of the Markdown field. |
### VulnerabilityDetailModuleLocation
Represents the vulnerability details location within a file in the project.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `moduleName` | String! | Module name. |
| `name` | String! | Name of the field. |
| `offset` | Int! | Offset of the module location. |
### VulnerabilityDetailTable
Represents the vulnerability details table value.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `headers` | VulnerabilityDetail! => Array | Table headers. |
| `name` | String! | Name of the field. |
| `rows` | VulnerabilityDetail! => Array | Table rows. |
### VulnerabilityDetailText
Represents the vulnerability details text field.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `name` | String! | Name of the field. |
| `value` | String! | Value of the text field. |
### VulnerabilityDetailUrl
Represents the vulnerability details URL field.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `description` | String! | Description of the field. |
| `fieldName` | String | Name of the field. |
| `href` | String! | Href of the URL. |
| `name` | String! | Name of the field. |
| `text` | String | Text of the URL. |
### VulnerabilityDismissPayload
Autogenerated return type of VulnerabilityDismiss.
......
# frozen_string_literal: true
module Resolvers
module Vulnerabilities
class DetailsResolver < BaseResolver
type [::Types::VulnerabilityDetailType], null: false
def resolve
return [] if object.finding_details.blank?
self.class.with_field_name(object.finding_details.with_indifferent_access)
end
def self.with_field_name(items)
return [] if items.blank?
items.map { |field_name, field| field.merge(field_name: field_name) }
end
end
end
end
# frozen_string_literal: true
module Types
class VulnerabilityDetailType < BaseUnion
UnexpectedReportType = Class.new(StandardError)
description 'Represents a vulnerability detail field. The fields with data will depend on the vulnerability detail type'
graphql_name 'VulnerabilityDetail'
possible_types VulnerabilityDetails::UrlType,
VulnerabilityDetails::IntType,
VulnerabilityDetails::ListType,
VulnerabilityDetails::CodeType,
VulnerabilityDetails::TextType,
VulnerabilityDetails::DiffType,
VulnerabilityDetails::TableType,
VulnerabilityDetails::BooleanType,
VulnerabilityDetails::CommitType,
VulnerabilityDetails::MarkdownType,
VulnerabilityDetails::FileLocationType,
VulnerabilityDetails::ModuleLocationType,
VulnerabilityDetails::BaseType
def self.resolve_type(object, context)
case object['type']
when 'url' then VulnerabilityDetails::UrlType
when 'code' then VulnerabilityDetails::CodeType
when 'text' then VulnerabilityDetails::TextType
when 'diff' then VulnerabilityDetails::DiffType
when 'table' then VulnerabilityDetails::TableType
when 'commit' then VulnerabilityDetails::CommitType
when 'markdown' then VulnerabilityDetails::MarkdownType
when 'file-location' then VulnerabilityDetails::FileLocationType
when 'module-location' then VulnerabilityDetails::ModuleLocationType
when 'list', 'named-list' then VulnerabilityDetails::ListType
else resolve_type_by_value(object['value'])
end
end
def self.resolve_type_by_value(value)
case value
when String then VulnerabilityDetails::TextType
when TrueClass, FalseClass then VulnerabilityDetails::BooleanType
when Integer then VulnerabilityDetails::IntType
else VulnerabilityDetails::BaseType
end
end
private_class_method :resolve_type_by_value
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class BaseType < BaseObject
graphql_name 'VulnerabilityDetailBase'
description 'Represents the vulnerability details base'
field :field_name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the field.'
field :name, GraphQL::STRING_TYPE, null: false,
description: 'Name of the field.'
field :description, GraphQL::STRING_TYPE, null: false,
description: 'Description of the field.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class BooleanType < BaseType
graphql_name 'VulnerabilityDetailBoolean'
description 'Represents the vulnerability details boolean value'
field :value, GraphQL::BOOLEAN_TYPE, null: false,
description: 'Value of the field.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class CodeType < BaseType
graphql_name 'VulnerabilityDetailCode'
description 'Represents the vulnerability details code field'
field :lang, GraphQL::STRING_TYPE, null: true,
description: 'Language of the code.'
field :value, GraphQL::STRING_TYPE, null: false,
description: 'Source code.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class CommitType < BaseType
graphql_name 'VulnerabilityDetailCommit'
description 'Represents the vulnerability details commit field'
field :value, GraphQL::STRING_TYPE, null: false,
description: 'The commit SHA value.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class DiffType < BaseType
graphql_name 'VulnerabilityDetailDiff'
description 'Represents the vulnerability details diff field'
field :before, GraphQL::STRING_TYPE, null: false,
description: 'Value of the field before the change.'
field :after, GraphQL::STRING_TYPE, null: false,
description: 'Value of the field after the change.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class FileLocationType < BaseType
graphql_name 'VulnerabilityDetailFileLocation'
description 'Represents the vulnerability details location within a file in the project'
field :file_name, GraphQL::STRING_TYPE, null: false,
description: 'File name.'
field :line_start, GraphQL::INT_TYPE, null: false,
description: 'Start line number of the file location.'
field :line_end, GraphQL::INT_TYPE, null: false,
description: 'End line number of the file location.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class IntType < BaseType
graphql_name 'VulnerabilityDetailInt'
description 'Represents the vulnerability details integer value'
field :value, GraphQL::INT_TYPE, null: false,
description: 'Value of the field.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class ListType < BaseType
graphql_name 'VulnerabilityDetailList'
description 'Represents the vulnerability details list value'
field :items, [VulnerabilityDetailType], null: false,
description: 'List of details.'
def items
return object[:items] || [] if object[:type] == 'list'
::Resolvers::Vulnerabilities::DetailsResolver.with_field_name(object[:items])
end
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class MarkdownType < BaseType
graphql_name 'VulnerabilityDetailMarkdown'
description 'Represents the vulnerability details Markdown field'
field :value, GraphQL::STRING_TYPE, null: false,
description: 'Value of the Markdown field.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class ModuleLocationType < BaseType
graphql_name 'VulnerabilityDetailModuleLocation'
description 'Represents the vulnerability details location within a file in the project'
field :module_name, GraphQL::STRING_TYPE, null: false,
description: 'Module name.'
field :offset, GraphQL::INT_TYPE, null: false,
description: 'Offset of the module location.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class TableType < BaseType
graphql_name 'VulnerabilityDetailTable'
description 'Represents the vulnerability details table value'
field :headers, [VulnerabilityDetailType], null: false,
description: 'Table headers.'
field :rows, [VulnerabilityDetailType], null: false,
description: 'Table rows.'
def headers
::Resolvers::Vulnerabilities::DetailsResolver.with_field_name(object[:headers])
end
def rows
::Resolvers::Vulnerabilities::DetailsResolver.with_field_name(object[:rows])
end
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class TextType < BaseType
graphql_name 'VulnerabilityDetailText'
description 'Represents the vulnerability details text field'
field :value, GraphQL::STRING_TYPE, null: false,
description: 'Value of the text field.'
end
end
end
# frozen_string_literal: true
module Types
module VulnerabilityDetails
# rubocop: disable Graphql/AuthorizeTypes
class UrlType < BaseType
graphql_name 'VulnerabilityDetailUrl'
description 'Represents the vulnerability details URL field'
field :text, GraphQL::STRING_TYPE, null: true,
description: 'Text of the URL.'
field :href, GraphQL::STRING_TYPE, null: false,
description: 'Href of the URL.'
end
end
end
......@@ -90,6 +90,10 @@ module Types
field :dismissed_by, ::Types::UserType, null: true,
description: 'The user that dismissed the vulnerability.'
field :details, [VulnerabilityDetailType], null: false,
description: 'Details of the vulnerability',
resolver: Resolvers::Vulnerabilities::DetailsResolver
def confirmed_by
::Gitlab::Graphql::Loaders::BatchModelLoader.new(::User, object.confirmed_by_id).find
end
......
......@@ -117,7 +117,7 @@ module EE
scope :with_limit, -> (maximum) { limit(maximum) }
delegate :scanner_name, :scanner_external_id, :metadata, :message, :description,
delegate :scanner_name, :scanner_external_id, :metadata, :message, :description, :details,
to: :finding, prefix: true, allow_nil: true
delegate :default_branch, :name, to: :project, prefix: true, allow_nil: true
......
---
title: Add details to Vulnerability GraphQL
merge_request: 49465
author:
type: added
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Vulnerabilities::DetailsResolver do
include GraphqlHelpers
describe '.with_field_name' do
subject { described_class.with_field_name(items) }
context 'when there are no items' do
let(:items) { nil }
it { is_expected.to eq([]) }
end
context 'when there are items with field name' do
let(:items) do
{
field: {
value: :x
},
field_2: {
value: :y
}
}
end
it { is_expected.to eq([{ value: :x, field_name: :field }, { value: :y, field_name: :field_2 }]) }
end
end
describe '#resolve' do
subject { resolve(described_class, obj: vulnerability, args: {}, ctx: {}) }
let(:vulnerability) { double(finding_details: finding_details) }
context 'when there are no items in finding details' do
let(:finding_details) { nil }
it { is_expected.to eq([]) }
end
context 'when there are items in finding details' do
let(:finding_details) do
{
field: {
value: :x
},
field_2: {
value: :y
}
}
end
it { is_expected.to eq([{ 'field_name' => 'field', 'value' => :x }, { 'field_name' => 'field_2', 'value' => :y }]) }
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetail'] do
let(:expected_types) do
[
Types::VulnerabilityDetails::UrlType,
Types::VulnerabilityDetails::IntType,
Types::VulnerabilityDetails::ListType,
Types::VulnerabilityDetails::CodeType,
Types::VulnerabilityDetails::TextType,
Types::VulnerabilityDetails::DiffType,
Types::VulnerabilityDetails::TableType,
Types::VulnerabilityDetails::CommitType,
Types::VulnerabilityDetails::BooleanType,
Types::VulnerabilityDetails::MarkdownType,
Types::VulnerabilityDetails::FileLocationType,
Types::VulnerabilityDetails::ModuleLocationType,
Types::VulnerabilityDetails::BaseType
]
end
it 'exposes all possible types' do
expect(described_class.possible_types).to contain_exactly(*expected_types)
end
describe '.resolve_type' do
using RSpec::Parameterized::TableSyntax
where(:type, :value, :graphql_type) do
'url' | nil | Types::VulnerabilityDetails::UrlType
'code' | nil | Types::VulnerabilityDetails::CodeType
'text' | nil | Types::VulnerabilityDetails::TextType
'diff' | nil | Types::VulnerabilityDetails::DiffType
'table' | nil | Types::VulnerabilityDetails::TableType
'commit' | nil | Types::VulnerabilityDetails::CommitType
'markdown' | nil | Types::VulnerabilityDetails::MarkdownType
'file-location' | nil | Types::VulnerabilityDetails::FileLocationType
'module-location' | nil | Types::VulnerabilityDetails::ModuleLocationType
'list' | nil | Types::VulnerabilityDetails::ListType
'named-list' | nil | Types::VulnerabilityDetails::ListType
'other' | nil | Types::VulnerabilityDetails::BaseType
'value' | nil | Types::VulnerabilityDetails::BaseType
'value' | '1' | Types::VulnerabilityDetails::TextType
'value' | 412 | Types::VulnerabilityDetails::IntType
'value' | true | Types::VulnerabilityDetails::BooleanType
'value' | false | Types::VulnerabilityDetails::BooleanType
end
with_them do
it 'correctly maps type in object to GraphQL type' do
expect(described_class.resolve_type({ 'type' => type, 'value' => value }, {})).to eq(graphql_type)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailBase'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailBoolean'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :value) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailCode'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :lang, :value) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailCommit'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :value) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailDiff'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :before, :after) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailFileLocation'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :fileName, :lineStart, :lineEnd) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailInt'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :value) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailList'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :items) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailMarkdown'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :value) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailModuleLocation'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :moduleName, :offset) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailTable'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :headers, :rows) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailText'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :value) }
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['VulnerabilityDetailUrl'] do
it { expect(described_class).to have_graphql_fields(:name, :description, :fieldName, :text, :href) }
end
......@@ -34,7 +34,8 @@ RSpec.describe GitlabSchema.types['Vulnerability'] do
discussions
confirmed_by
resolved_by
dismissed_by]
dismissed_by
details]
end
before do
......
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