Commit 2c6b1c39 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '321966-add-search-instance-security-dashboard-projects' into 'master'

Add ability to search instanceSecurityDashboard.projects GraphQL query

See merge request gitlab-org/gitlab!62933
parents a3645c1c e6d18ad7
......@@ -9686,12 +9686,27 @@ A block of time for which a participant is on-call.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="instancesecuritydashboardprojects"></a>`projects` | [`ProjectConnection!`](#projectconnection) | Projects selected in Instance Security Dashboard. (see [Connections](#connections)) |
| <a id="instancesecuritydashboardvulnerabilitygrades"></a>`vulnerabilityGrades` | [`[VulnerableProjectsByGrade!]!`](#vulnerableprojectsbygrade) | Represents vulnerable project counts for each grade. |
| <a id="instancesecuritydashboardvulnerabilityscanners"></a>`vulnerabilityScanners` | [`VulnerabilityScannerConnection`](#vulnerabilityscannerconnection) | Vulnerability scanners reported on the vulnerabilities from projects selected in Instance Security Dashboard. (see [Connections](#connections)) |
#### Fields with arguments
##### `InstanceSecurityDashboard.projects`
Projects selected in Instance Security Dashboard.
Returns [`ProjectConnection!`](#projectconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="instancesecuritydashboardprojectssearch"></a>`search` | [`String`](#string) | Search query for project name, path, or description. |
##### `InstanceSecurityDashboard.vulnerabilitySeveritiesCount`
Counts for each vulnerability severity from projects selected in Instance Security Dashboard.
......
......@@ -5,10 +5,15 @@ module Resolvers
class ProjectsResolver < BaseResolver
type ::Types::ProjectType, null: true
argument :search, GraphQL::STRING_TYPE,
required: false,
description: 'Search query for project name, path, or description.'
alias_method :dashboard, :object
def resolve(**args)
dashboard&.projects
projects = dashboard&.projects
args[:search] ? projects&.search(args[:search]) : projects
end
end
end
......
......@@ -9,7 +9,8 @@ module Types
field :projects,
Types::ProjectType.connection_type,
null: false,
description: 'Projects selected in Instance Security Dashboard.'
description: 'Projects selected in Instance Security Dashboard.',
resolver: ::Resolvers::InstanceSecurityDashboard::ProjectsResolver
field :vulnerability_scanners,
::Types::VulnerabilityScannerType.connection_type,
......
......@@ -6,15 +6,21 @@ RSpec.describe Resolvers::InstanceSecurityDashboard::ProjectsResolver do
include GraphqlHelpers
describe '#resolve' do
subject { resolve(described_class, obj: object, ctx: { current_user: user }) }
subject { resolve(described_class, obj: object, args: filters, ctx: { current_user: user }) }
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user, security_dashboard_projects: [project]) }
let_it_be(:project1) { create(:project, description: "Description for project1") }
let_it_be(:project2) { create(:project, description: "Description for project2") }
let_it_be(:user) { create(:user, security_dashboard_projects: [project1, project2]) }
let_it_be(:filters) { {} }
let_it_be(:object) { InstanceSecurityDashboard.new(user) }
context 'when provided object is InstanceSecurityDashboard' do
let(:object) { InstanceSecurityDashboard.new(user) }
before_all do
project1.add_developer(user)
project2.add_developer(user)
end
it { is_expected.to eq(object.projects) }
context 'when provided object is InstanceSecurityDashboard' do
it { is_expected.to eq([project1, project2]) }
end
context 'when object is not provided' do
......@@ -22,5 +28,31 @@ RSpec.describe Resolvers::InstanceSecurityDashboard::ProjectsResolver do
it { is_expected.to be_nil }
end
context 'when search filter is provided' do
context 'search by name' do
let(:filters) { { search: project1.name } }
it 'returns matching project' do
is_expected.to contain_exactly(project1)
end
end
context 'search by path' do
let(:filters) { { search: project1.path } }
it 'returns matching project' do
is_expected.to contain_exactly(project1)
end
end
context 'search by description' do
let(:filters) { { search: project1.description } }
it 'returns matching project' do
is_expected.to contain_exactly(project1)
end
end
end
end
end
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