Commit 5e674f44 authored by Dmitry Gruzd's avatar Dmitry Gruzd Committed by Dylan Griffith

Add issues/merge_requests filtering by state for search API

parent fd39a861
---
title: Add issues and merge_requests filtering by state for search API
merge_request: 41989
author:
type: added
...@@ -397,6 +397,7 @@ GET /groups/:id/search ...@@ -397,6 +397,7 @@ GET /groups/:id/search
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `scope` | string | yes | The scope to search in | | `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query | | `search` | string | yes | The search query |
| `state` | string | no | Filtering by state, currently only supported for issues and merge requests. It is ignored for other scopes |
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, users. Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, users.
...@@ -741,6 +742,7 @@ GET /projects/:id/search ...@@ -741,6 +742,7 @@ GET /projects/:id/search
| `scope` | string | yes | The scope to search in | | `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query | | `search` | string | yes | The search query |
| `ref` | string | no | The name of a repository branch or tag to search on. The project's default branch is used by default. This is only applicable for scopes: commits, blobs, and wiki_blobs. | | `ref` | string | no | The name of a repository branch or tag to search on. The project's default branch is used by default. This is only applicable for scopes: commits, blobs, and wiki_blobs. |
| `state` | string | no | Filtering by state, currently only supported for issues and merge requests. It is ignored for other scopes |
Search the expression within the specified scope. Currently these scopes are supported: issues, merge_requests, milestones, notes, wiki_blobs, commits, blobs, users. Search the expression within the specified scope. Currently these scopes are supported: issues, merge_requests, milestones, notes, wiki_blobs, commits, blobs, users.
......
...@@ -9,7 +9,7 @@ module Elastic ...@@ -9,7 +9,7 @@ module Elastic
state = options[:state] state = options[:state]
return query_hash if state.blank? || state == 'all' return query_hash if state.blank? || state == 'all'
return query_hash unless %w(all opened closed merged).include?(state) return query_hash unless API::Helpers::SearchHelpers.search_states.include?(state)
filter = { match: { state: state } } filter = { match: { state: state } }
......
...@@ -17,6 +17,10 @@ module API ...@@ -17,6 +17,10 @@ module API
# This is a separate method so that EE can redefine it. # This is a separate method so that EE can redefine it.
%w(issues merge_requests milestones notes wiki_blobs commits blobs users) %w(issues merge_requests milestones notes wiki_blobs commits blobs users)
end end
def self.search_states
%w(all opened closed merged)
end
end end
end end
end end
......
...@@ -32,6 +32,7 @@ module API ...@@ -32,6 +32,7 @@ module API
search_params = { search_params = {
scope: params[:scope], scope: params[:scope],
search: params[:search], search: params[:search],
state: params[:state],
snippets: snippets?, snippets: snippets?,
page: params[:page], page: params[:page],
per_page: params[:per_page] per_page: params[:per_page]
...@@ -79,6 +80,7 @@ module API ...@@ -79,6 +80,7 @@ module API
type: String, type: String,
desc: 'The scope of the search', desc: 'The scope of the search',
values: Helpers::SearchHelpers.global_search_scopes values: Helpers::SearchHelpers.global_search_scopes
optional :state, type: String, desc: 'Filter results by state', values: Helpers::SearchHelpers.search_states
use :pagination use :pagination
end end
get do get do
...@@ -100,6 +102,7 @@ module API ...@@ -100,6 +102,7 @@ module API
type: String, type: String,
desc: 'The scope of the search', desc: 'The scope of the search',
values: Helpers::SearchHelpers.group_search_scopes values: Helpers::SearchHelpers.group_search_scopes
optional :state, type: String, desc: 'Filter results by state', values: Helpers::SearchHelpers.search_states
use :pagination use :pagination
end end
get ':id/(-/)search' do get ':id/(-/)search' do
...@@ -122,6 +125,7 @@ module API ...@@ -122,6 +125,7 @@ module API
desc: 'The scope of the search', desc: 'The scope of the search',
values: Helpers::SearchHelpers.project_search_scopes values: Helpers::SearchHelpers.project_search_scopes
optional :ref, type: String, desc: 'The name of a repository branch or tag. If not given, the default branch is used' optional :ref, type: String, desc: 'The name of a repository branch or tag. If not given, the default branch is used'
optional :state, type: String, desc: 'Filter results by state', values: Helpers::SearchHelpers.search_states
use :pagination use :pagination
end end
get ':id/(-/)search' do get ':id/(-/)search' do
......
...@@ -47,6 +47,17 @@ RSpec.describe API::Search do ...@@ -47,6 +47,17 @@ RSpec.describe API::Search do
end end
end end
shared_examples 'filter by state' do |scope:, search:|
it 'respects scope filtering' do
get api(endpoint, user), params: { scope: scope, search: search, state: state }
documents = Gitlab::Json.parse(response.body)
expect(documents.count).to eq(1)
expect(documents.first['state']).to eq(state)
end
end
describe 'GET /search' do describe 'GET /search' do
let(:endpoint) { '/search' } let(:endpoint) { '/search' }
...@@ -88,42 +99,84 @@ RSpec.describe API::Search do ...@@ -88,42 +99,84 @@ RSpec.describe API::Search do
end end
context 'for issues scope' do context 'for issues scope' do
before do context 'without filtering by state' do
create(:issue, project: project, title: 'awesome issue') before do
create(:issue, project: project, title: 'awesome issue')
get api(endpoint, user), params: { scope: 'issues', search: 'awesome' } get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
end end
it_behaves_like 'response is correct', schema: 'public_api/v4/issues' it_behaves_like 'response is correct', schema: 'public_api/v4/issues'
it_behaves_like 'ping counters', scope: :issues it_behaves_like 'ping counters', scope: :issues
describe 'pagination' do describe 'pagination' do
before do
create(:issue, project: project, title: 'another issue')
end
include_examples 'pagination', scope: :issues
end
end
context 'filter by state' do
before do before do
create(:issue, project: project, title: 'another issue') create(:issue, project: project, title: 'awesome opened issue')
create(:issue, :closed, project: project, title: 'awesome closed issue')
end end
include_examples 'pagination', scope: :issues context 'state: opened' do
let(:state) { 'opened' }
include_examples 'filter by state', scope: :issues, search: 'awesome'
end
context 'state: closed' do
let(:state) { 'closed' }
include_examples 'filter by state', scope: :issues, search: 'awesome'
end
end end
end end
context 'for merge_requests scope' do context 'for merge_requests scope' do
before do context 'without filtering by state' do
create(:merge_request, source_project: repo_project, title: 'awesome mr') before do
create(:merge_request, source_project: repo_project, title: 'awesome mr')
get api(endpoint, user), params: { scope: 'merge_requests', search: 'awesome' } get api(endpoint, user), params: { scope: 'merge_requests', search: 'awesome' }
end end
it_behaves_like 'response is correct', schema: 'public_api/v4/merge_requests' it_behaves_like 'response is correct', schema: 'public_api/v4/merge_requests'
it_behaves_like 'ping counters', scope: :merge_requests it_behaves_like 'ping counters', scope: :merge_requests
describe 'pagination' do describe 'pagination' do
before do
create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch')
end
include_examples 'pagination', scope: :merge_requests
end
end
context 'filter by state' do
before do before do
create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch') create(:merge_request, source_project: project, title: 'awesome opened mr')
create(:merge_request, :closed, project: project, title: 'awesome closed mr')
end end
include_examples 'pagination', scope: :merge_requests context 'state: opened' do
let(:state) { 'opened' }
include_examples 'filter by state', scope: :merge_requests, search: 'awesome'
end
context 'state: closed' do
let(:state) { 'closed' }
include_examples 'filter by state', scope: :merge_requests, search: 'awesome'
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