Commit dad714c5 authored by Tiger Watson's avatar Tiger Watson

Merge branch 'sy-add-escalation-policy-search-param' into 'master'

Add ability to search for escalation policies by name

See merge request gitlab-org/gitlab!78950
parents fafe47e5 f7bb2b1d
......@@ -13328,7 +13328,6 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projecthttpurltorepo"></a>`httpUrlToRepo` | [`String`](#string) | URL to connect to the project via HTTPS. |
| <a id="projectid"></a>`id` | [`ID!`](#id) | ID of the project. |
| <a id="projectimportstatus"></a>`importStatus` | [`String`](#string) | Status of import background job of the project. |
| <a id="projectincidentmanagementescalationpolicies"></a>`incidentManagementEscalationPolicies` | [`EscalationPolicyTypeConnection`](#escalationpolicytypeconnection) | Incident Management escalation policies of the project. (see [Connections](#connections)) |
| <a id="projectissuesenabled"></a>`issuesEnabled` | [`Boolean`](#boolean) | Indicates if Issues are enabled for the current user. |
| <a id="projectjiraimportstatus"></a>`jiraImportStatus` | [`String`](#string) | Status of Jira import background job of the project. |
| <a id="projectjiraimports"></a>`jiraImports` | [`JiraImportConnection`](#jiraimportconnection) | Jira imports into the project. (see [Connections](#connections)) |
......@@ -13637,6 +13636,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectenvironmentssearch"></a>`search` | [`String`](#string) | Search query for environment name. |
| <a id="projectenvironmentsstates"></a>`states` | [`[String!]`](#string) | States of environments that should be included in result. |
##### `Project.incidentManagementEscalationPolicies`
Incident Management escalation policies of the project.
Returns [`EscalationPolicyTypeConnection`](#escalationpolicytypeconnection).
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="projectincidentmanagementescalationpoliciesname"></a>`name` | [`String`](#string) | Fuzzy search by escalation policy name. |
##### `Project.incidentManagementEscalationPolicy`
Incident Management escalation policy of the project.
......@@ -13648,6 +13663,7 @@ Returns [`EscalationPolicyType`](#escalationpolicytype).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectincidentmanagementescalationpolicyid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | ID of the escalation policy. |
| <a id="projectincidentmanagementescalationpolicyname"></a>`name` | [`String`](#string) | Fuzzy search by escalation policy name. |
##### `Project.incidentManagementOncallSchedules`
......@@ -12,6 +12,7 @@ module IncidentManagement
return IncidentManagement::EscalationPolicy.none unless allowed?
collection = project.incident_management_escalation_policies
collection = by_name_search(collection)
by_id(collection)
end
......@@ -28,5 +29,11 @@ module IncidentManagement
collection.id_in(params[:id])
end
def by_name_search(collection)
return collection unless params[:name_search].present?
collection.search_by_name(params[:name_search])
end
end
end
......@@ -9,6 +9,11 @@ module Resolvers
type Types::IncidentManagement::EscalationPolicyType.connection_type, null: true
argument :name,
GraphQL::Types::String,
required: false,
description: 'Fuzzy search by escalation policy name.'
when_single do
argument :id,
::Types::GlobalIDType[::IncidentManagement::EscalationPolicy],
......@@ -17,10 +22,16 @@ module Resolvers
prepare: ->(id, ctx) { id.model_id }
end
def resolve_with_lookahead(**args)
def resolve_with_lookahead(name: nil, **args)
context[:execution_time] = Time.current
apply_lookahead(::IncidentManagement::EscalationPoliciesFinder.new(current_user, project, args).execute)
apply_lookahead(
::IncidentManagement::EscalationPoliciesFinder.new(
current_user,
project,
{ name_search: name, **args }
).execute
)
end
private
......
......@@ -2,6 +2,8 @@
module IncidentManagement
class EscalationPolicy < ApplicationRecord
include Gitlab::SQL::Pattern
self.table_name = 'incident_management_escalation_policies'
belongs_to :project
......@@ -13,6 +15,7 @@ module IncidentManagement
validates :description, length: { maximum: 160 }
scope :for_project, -> (project) { where(project: project) }
scope :search_by_name, -> (query) { fuzzy_search(query, [:name]) }
accepts_nested_attributes_for :rules
......
......@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe IncidentManagement::EscalationPoliciesFinder do
let_it_be(:current_user) { create(:user) }
let_it_be_with_refind(:project) { create(:project) }
let_it_be(:escalation_policy) { create(:incident_management_escalation_policy, project: project) }
let_it_be(:escalation_policy) { create(:incident_management_escalation_policy, project: project, name: 'unique identifier') }
let_it_be(:escalation_policy_from_another_project) { create(:incident_management_escalation_policy) }
let(:params) { {} }
......@@ -32,6 +32,18 @@ RSpec.describe IncidentManagement::EscalationPoliciesFinder do
it { is_expected.to contain_exactly(escalation_policy) }
end
context 'when search_name is given' do
let(:params) { { name_search: 'ique iden' } }
it { is_expected.to contain_exactly(escalation_policy) }
context 'when the name does not match' do
let(:params) { { name_search: 'not a matching search' } }
it { is_expected.to eq(IncidentManagement::EscalationPolicy.none) }
end
end
end
context 'when user has no permissions' do
......
......@@ -7,7 +7,8 @@ RSpec.describe Resolvers::IncidentManagement::EscalationPoliciesResolver do
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:policy) { create(:incident_management_escalation_policy, project: project) }
let_it_be(:policy) { create(:incident_management_escalation_policy, project: project, name: 'Target policy') }
let_it_be(:other_policy) { create(:incident_management_escalation_policy) }
let(:args) { {} }
let(:resolver) { described_class }
......@@ -29,6 +30,16 @@ RSpec.describe Resolvers::IncidentManagement::EscalationPoliciesResolver do
expect(resolved_policies.first).to have_attributes(id: policy.id)
end
context 'with name param provided' do
let(:args) { { name: 'target' } }
it 'returns escalation policies matching the name search' do
expect(resolved_policies.length).to eq(1)
expect(resolved_policies.first).to be_a(::IncidentManagement::EscalationPolicy)
expect(resolved_policies.first).to have_attributes(id: policy.id)
end
end
context 'when resolving a single item' do
let(:resolver) { described_class.single }
......
......@@ -38,12 +38,18 @@ RSpec.describe IncidentManagement::EscalationPolicy do
describe 'scopes' do
let_it_be(:project) { create(:project) }
let_it_be(:policy) { create(:incident_management_escalation_policy, project: project) }
let_it_be(:other_policy) { create(:incident_management_escalation_policy) }
let_it_be(:other_policy) { create(:incident_management_escalation_policy, name: 'Other policy') }
describe '.for_project' do
subject { described_class.for_project(project) }
it { is_expected.to contain_exactly(policy) }
end
describe '.search_by_name' do
subject { described_class.search_by_name('other') }
it { is_expected.to contain_exactly(other_policy) }
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