Commit d43c4bf3 authored by Tiger Watson's avatar Tiger Watson

Merge branch '213884-alert-management-plain-text-search' into 'master'

Add search to Alert Management Alerts GraphQL query

See merge request gitlab-org/gitlab!32047
parents f958fd99 19b7a490
...@@ -13,6 +13,7 @@ module AlertManagement ...@@ -13,6 +13,7 @@ module AlertManagement
collection = project.alert_management_alerts collection = project.alert_management_alerts
collection = by_status(collection) collection = by_status(collection)
collection = by_search(collection)
collection = by_iid(collection) collection = by_iid(collection)
sort(collection) sort(collection)
end end
...@@ -33,6 +34,10 @@ module AlertManagement ...@@ -33,6 +34,10 @@ module AlertManagement
values.present? ? collection.for_status(values) : collection values.present? ? collection.for_status(values) : collection
end end
def by_search(collection)
params[:search].present? ? collection.search(params[:search]) : collection
end
def sort(collection) def sort(collection)
params[:sort] ? collection.sort_by_attribute(params[:sort]) : collection params[:sort] ? collection.sort_by_attribute(params[:sort]) : collection
end end
......
...@@ -15,6 +15,10 @@ module Resolvers ...@@ -15,6 +15,10 @@ module Resolvers
description: 'Sort alerts by this criteria', description: 'Sort alerts by this criteria',
required: false required: false
argument :search, GraphQL::STRING_TYPE,
description: 'Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.',
required: false
type Types::AlertManagement::AlertType, null: true type Types::AlertManagement::AlertType, null: true
def resolve(**args) def resolve(**args)
......
...@@ -5,6 +5,7 @@ module AlertManagement ...@@ -5,6 +5,7 @@ module AlertManagement
include AtomicInternalId include AtomicInternalId
include ShaAttribute include ShaAttribute
include Sortable include Sortable
include Gitlab::SQL::Pattern
STATUSES = { STATUSES = {
triggered: 0, triggered: 0,
...@@ -97,6 +98,7 @@ module AlertManagement ...@@ -97,6 +98,7 @@ module AlertManagement
scope :for_iid, -> (iid) { where(iid: iid) } scope :for_iid, -> (iid) { where(iid: iid) }
scope :for_status, -> (status) { where(status: status) } scope :for_status, -> (status) { where(status: status) }
scope :for_fingerprint, -> (project, fingerprint) { where(project: project, fingerprint: fingerprint) } scope :for_fingerprint, -> (project, fingerprint) { where(project: project, fingerprint: fingerprint) }
scope :search, -> (query) { fuzzy_search(query, [:title, :description, :monitoring_tool, :service]) }
scope :order_start_time, -> (sort_order) { order(started_at: sort_order) } scope :order_start_time, -> (sort_order) { order(started_at: sort_order) }
scope :order_end_time, -> (sort_order) { order(ended_at: sort_order) } scope :order_end_time, -> (sort_order) { order(ended_at: sort_order) }
......
---
title: Add search to Alert Management Alerts GraphQL query
merge_request: 32047
author:
type: added
...@@ -7302,6 +7302,11 @@ type Project { ...@@ -7302,6 +7302,11 @@ type Project {
""" """
iid: String iid: String
"""
Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.
"""
search: String
""" """
Sort alerts by this criteria Sort alerts by this criteria
""" """
...@@ -7342,6 +7347,11 @@ type Project { ...@@ -7342,6 +7347,11 @@ type Project {
""" """
last: Int last: Int
"""
Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.
"""
search: String
""" """
Sort alerts by this criteria Sort alerts by this criteria
""" """
......
...@@ -21865,6 +21865,16 @@ ...@@ -21865,6 +21865,16 @@
"ofType": null "ofType": null
}, },
"defaultValue": null "defaultValue": null
},
{
"name": "search",
"description": "Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
} }
], ],
"type": { "type": {
...@@ -21917,6 +21927,16 @@ ...@@ -21917,6 +21927,16 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "search",
"description": "Search criteria for filtering alerts. This will search on title, description, service, monitoring_tool.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "after", "name": "after",
"description": "Returns the elements in the list that come after the specified cursor.", "description": "Returns the elements in the list that come after the specified cursor.",
...@@ -24,6 +24,10 @@ FactoryBot.define do ...@@ -24,6 +24,10 @@ FactoryBot.define do
monitoring_tool { FFaker::AWS.product_description } monitoring_tool { FFaker::AWS.product_description }
end end
trait :with_description do
description { FFaker::Lorem.sentence }
end
trait :with_host do trait :with_host do
hosts { [FFaker::Internet.ip_v4_address] } hosts { [FFaker::Internet.ip_v4_address] }
end end
...@@ -70,6 +74,7 @@ FactoryBot.define do ...@@ -70,6 +74,7 @@ FactoryBot.define do
with_service with_service
with_monitoring_tool with_monitoring_tool
with_host with_host
with_description
low_severity low_severity
end end
end end
......
...@@ -5,9 +5,9 @@ require 'spec_helper' ...@@ -5,9 +5,9 @@ require 'spec_helper'
describe AlertManagement::AlertsFinder, '#execute' do describe AlertManagement::AlertsFinder, '#execute' do
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:alert_1) { create(:alert_management_alert, :resolved, project: project, ended_at: 1.year.ago, events: 2, severity: :high) } let_it_be(:alert_1) { create(:alert_management_alert, :all_fields, :resolved, project: project, ended_at: 1.year.ago, events: 2, severity: :high) }
let_it_be(:alert_2) { create(:alert_management_alert, :ignored, project: project, events: 1, severity: :critical) } let_it_be(:alert_2) { create(:alert_management_alert, :all_fields, :ignored, project: project, events: 1, severity: :critical) }
let_it_be(:alert_3) { create(:alert_management_alert) } let_it_be(:alert_3) { create(:alert_management_alert, :all_fields) }
let(:params) { {} } let(:params) { {} }
subject { described_class.new(current_user, project, params).execute } subject { described_class.new(current_user, project, params).execute }
...@@ -222,5 +222,59 @@ describe AlertManagement::AlertsFinder, '#execute' do ...@@ -222,5 +222,59 @@ describe AlertManagement::AlertsFinder, '#execute' do
end end
end end
end end
context 'search query given' do
let_it_be(:alert) do
create(:alert_management_alert,
:with_fingerprint,
title: 'Title',
description: 'Desc',
service: 'Service',
monitoring_tool: 'Monitor'
)
end
before do
alert.project.add_developer(current_user)
end
subject { described_class.new(current_user, alert.project, params).execute }
context 'searching title' do
let(:params) { { search: alert.title } }
it { is_expected.to match_array([alert]) }
end
context 'searching description' do
let(:params) { { search: alert.description } }
it { is_expected.to match_array([alert]) }
end
context 'searching service' do
let(:params) { { search: alert.service } }
it { is_expected.to match_array([alert]) }
end
context 'searching monitoring tool' do
let(:params) { { search: alert.monitoring_tool } }
it { is_expected.to match_array([alert]) }
end
context 'searching something else' do
let(:params) { { search: alert.fingerprint } }
it { is_expected.to be_empty }
end
context 'empty search' do
let(:params) { { search: ' ' } }
it { is_expected.to match_array([alert]) }
end
end
end end
end end
...@@ -162,7 +162,50 @@ describe AlertManagement::Alert do ...@@ -162,7 +162,50 @@ describe AlertManagement::Alert do
it { is_expected.to contain_exactly(alert_1) } it { is_expected.to contain_exactly(alert_1) }
end end
describe '.details' do describe '.search' do
let_it_be(:alert) do
create(:alert_management_alert,
title: 'Title',
description: 'Desc',
service: 'Service',
monitoring_tool: 'Monitor'
)
end
subject { AlertManagement::Alert.search(query) }
context 'does not contain search string' do
let(:query) { 'something else' }
it { is_expected.to be_empty }
end
context 'title includes query' do
let(:query) { alert.title.upcase }
it { is_expected.to contain_exactly(alert) }
end
context 'description includes query' do
let(:query) { alert.description.upcase }
it { is_expected.to contain_exactly(alert) }
end
context 'service includes query' do
let(:query) { alert.service.upcase }
it { is_expected.to contain_exactly(alert) }
end
context 'monitoring tool includes query' do
let(:query) { alert.monitoring_tool.upcase }
it { is_expected.to contain_exactly(alert) }
end
end
describe '#details' do
let(:payload) do let(:payload) do
{ {
'title' => 'Details title', 'title' => 'Details title',
......
...@@ -10,6 +10,7 @@ describe 'getting Alert Management Alerts' do ...@@ -10,6 +10,7 @@ describe 'getting Alert Management Alerts' do
let_it_be(:alert_1) { create(:alert_management_alert, :all_fields, :resolved, project: project, issue: nil, severity: :low) } let_it_be(:alert_1) { create(:alert_management_alert, :all_fields, :resolved, project: project, issue: nil, severity: :low) }
let_it_be(:alert_2) { create(:alert_management_alert, :all_fields, project: project, severity: :critical, payload: payload) } let_it_be(:alert_2) { create(:alert_management_alert, :all_fields, project: project, severity: :critical, payload: payload) }
let_it_be(:other_project_alert) { create(:alert_management_alert, :all_fields) } let_it_be(:other_project_alert) { create(:alert_management_alert, :all_fields) }
let(:params) { {} }
let(:fields) do let(:fields) do
<<~QUERY <<~QUERY
...@@ -23,7 +24,7 @@ describe 'getting Alert Management Alerts' do ...@@ -23,7 +24,7 @@ describe 'getting Alert Management Alerts' do
graphql_query_for( graphql_query_for(
'project', 'project',
{ 'fullPath' => project.full_path }, { 'fullPath' => project.full_path },
query_graphql_field('alertManagementAlerts', {}, fields) query_graphql_field('alertManagementAlerts', params, fields)
) )
end end
...@@ -83,13 +84,7 @@ describe 'getting Alert Management Alerts' do ...@@ -83,13 +84,7 @@ describe 'getting Alert Management Alerts' do
end end
context 'with iid given' do context 'with iid given' do
let(:query) do let(:params) { { iid: alert_1.iid.to_s } }
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
query_graphql_field('alertManagementAlerts', { iid: alert_1.iid.to_s }, fields)
)
end
it_behaves_like 'a working graphql query' it_behaves_like 'a working graphql query'
...@@ -98,14 +93,6 @@ describe 'getting Alert Management Alerts' do ...@@ -98,14 +93,6 @@ describe 'getting Alert Management Alerts' do
end end
context 'sorting data given' do context 'sorting data given' do
let(:query) do
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
query_graphql_field('alertManagementAlerts', params, fields)
)
end
let(:params) { 'sort: SEVERITY_DESC' } let(:params) { 'sort: SEVERITY_DESC' }
let(:iids) { alerts.map { |a| a['iid'] } } let(:iids) { alerts.map { |a| a['iid'] } }
...@@ -123,6 +110,21 @@ describe 'getting Alert Management Alerts' do ...@@ -123,6 +110,21 @@ describe 'getting Alert Management Alerts' do
end end
end end
end end
context 'searching' do
let(:params) { { search: alert_1.title } }
it_behaves_like 'a working graphql query'
it { expect(alerts.size).to eq(1) }
it { expect(first_alert['iid']).to eq(alert_1.iid.to_s) }
context 'unknown criteria' do
let(:params) { { search: 'something random' } }
it { expect(alerts.size).to eq(0) }
end
end
end 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