debian-mirror-gitlab/spec/requests/api/search_spec.rb

1037 lines
34 KiB
Ruby
Raw Permalink Normal View History

2019-12-26 22:10:19 +05:30
# frozen_string_literal: true
2018-03-17 18:26:18 +05:30
require 'spec_helper'
2023-07-09 08:55:56 +05:30
RSpec.describe API::Search, :clean_gitlab_redis_rate_limiting, feature_category: :global_search do
2020-03-13 15:44:24 +05:30
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :wiki_repo, :public, name: 'awesome project', group: group) }
let_it_be(:repo_project) { create(:project, :public, :repository, group: group) }
2018-03-17 18:26:18 +05:30
2022-05-07 20:08:51 +05:30
before do
2022-10-11 01:57:18 +05:30
allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).and_return(0)
2022-05-07 20:08:51 +05:30
end
2018-03-17 18:26:18 +05:30
shared_examples 'response is correct' do |schema:, size: 1|
2020-04-08 14:13:33 +05:30
it { expect(response).to have_gitlab_http_status(:ok) }
2018-03-17 18:26:18 +05:30
it { expect(response).to match_response_schema(schema) }
it { expect(response).to include_limited_pagination_headers }
it { expect(json_response.size).to eq(size) }
end
2020-06-23 00:09:42 +05:30
shared_examples 'ping counters' do |scope:, search: ''|
it 'increases usage ping searches counter' do
expect(Gitlab::UsageDataCounters::SearchCounter).to receive(:count).with(:all_searches)
get api(endpoint, user), params: { scope: scope, search: search }
end
end
2023-01-13 00:05:48 +05:30
shared_examples 'apdex recorded' do |scope:, level:, search: ''|
it 'increments the custom search sli apdex' do
expect(Gitlab::Metrics::GlobalSearchSlis).to receive(:record_apdex).with(
elapsed: a_kind_of(Numeric),
search_scope: scope,
search_type: 'basic',
search_level: level
)
get api(endpoint, user), params: { scope: scope, search: search }
end
end
2021-01-29 00:20:46 +05:30
shared_examples 'orderable by created_at' do |scope:|
it 'allows ordering results by created_at asc' do
get api(endpoint, user), params: { scope: scope, search: 'sortable', order_by: 'created_at', sort: 'asc' }
expect(response).to have_gitlab_http_status(:success)
expect(json_response.count).to be > 1
created_ats = json_response.map { |r| Time.parse(r['created_at']) }
expect(created_ats.uniq.count).to be > 1
expect(created_ats).to eq(created_ats.sort)
end
it 'allows ordering results by created_at desc' do
get api(endpoint, user), params: { scope: scope, search: 'sortable', order_by: 'created_at', sort: 'desc' }
expect(response).to have_gitlab_http_status(:success)
expect(json_response.count).to be > 1
created_ats = json_response.map { |r| Time.parse(r['created_at']) }
expect(created_ats.uniq.count).to be > 1
expect(created_ats).to eq(created_ats.sort.reverse)
end
end
shared_examples 'issues orderable by created_at' do
before do
create_list(:issue, 3, title: 'sortable item', project: project)
end
it_behaves_like 'orderable by created_at', scope: :issues
end
shared_examples 'merge_requests orderable by created_at' do
before do
create_list(:merge_request, 3, :unique_branches, title: 'sortable item', target_project: repo_project, source_project: repo_project)
end
it_behaves_like 'orderable by created_at', scope: :merge_requests
end
2020-05-24 23:13:21 +05:30
shared_examples 'pagination' do |scope:, search: ''|
it 'returns a different result for each page' do
get api(endpoint, user), params: { scope: scope, search: search, page: 1, per_page: 1 }
first = json_response.first
get api(endpoint, user), params: { scope: scope, search: search, page: 2, per_page: 1 }
second = Gitlab::Json.parse(response.body).first
expect(first).not_to eq(second)
end
it 'returns 1 result when per_page is 1' do
get api(endpoint, user), params: { scope: scope, search: search, per_page: 1 }
expect(json_response.count).to eq(1)
end
it 'returns 2 results when per_page is 2' do
get api(endpoint, user), params: { scope: scope, search: search, per_page: 2 }
expect(Gitlab::Json.parse(response.body).count).to eq(2)
end
end
2020-11-24 15:15:51 +05:30
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
2021-01-03 14:25:43 +05:30
shared_examples 'filter by confidentiality' do |scope:, search:|
it 'respects confidentiality filtering' do
get api(endpoint, user), params: { scope: scope, search: search, confidential: confidential.to_s }
documents = Gitlab::Json.parse(response.body)
expect(documents.count).to eq(1)
expect(documents.first['confidential']).to eq(confidential)
end
end
2020-05-24 23:13:21 +05:30
describe 'GET /search' do
let(:endpoint) { '/search' }
2018-03-17 18:26:18 +05:30
context 'when user is not authenticated' do
it 'returns 401 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint), params: { scope: 'projects', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:unauthorized)
2018-03-17 18:26:18 +05:30
end
end
2023-06-20 00:43:36 +05:30
context 'when DB timeouts occur from global searches', :aggregate_failures do
2022-01-26 12:08:38 +05:30
%w(
issues
merge_requests
milestones
projects
snippet_titles
users
).each do |scope|
it "returns a 408 error if search with scope: #{scope} times out" do
allow(SearchService).to receive(:new).and_raise ActiveRecord::QueryCanceled
get api(endpoint, user), params: { scope: scope, search: 'awesome' }
expect(response).to have_gitlab_http_status(:request_timeout)
end
end
end
2018-03-17 18:26:18 +05:30
context 'when scope is not supported' do
it 'returns 400 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'unsupported', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:bad_request)
2018-03-17 18:26:18 +05:30
end
end
context 'when scope is missing' do
it 'returns 400 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:bad_request)
2018-03-17 18:26:18 +05:30
end
end
2023-05-27 22:25:52 +05:30
context 'when there is a search error' do
let(:results) { instance_double('Gitlab::SearchResults', failed?: true, error: 'failed to parse query') }
before do
allow_next_instance_of(SearchService) do |service|
allow(service).to receive(:search_objects).and_return([])
allow(service).to receive(:search_results).and_return(results)
end
end
it 'returns 400 error' do
get api(endpoint, user), params: { scope: 'issues', search: 'expected to fail' }
expect(response).to have_gitlab_http_status(:bad_request)
end
end
2018-03-17 18:26:18 +05:30
context 'with correct params' do
context 'for projects scope' do
before do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'projects', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/projects'
2020-05-24 23:13:21 +05:30
it_behaves_like 'pagination', scope: :projects
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :projects
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'projects', level: 'global'
2018-03-17 18:26:18 +05:30
end
context 'for issues scope' do
2020-11-24 15:15:51 +05:30
context 'without filtering by state' do
before do
create(:issue, project: project, title: 'awesome issue')
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
end
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
it_behaves_like 'response is correct', schema: 'public_api/v4/issues'
2020-05-24 23:13:21 +05:30
2020-11-24 15:15:51 +05:30
it_behaves_like 'ping counters', scope: :issues
2020-06-23 00:09:42 +05:30
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'issues', level: 'global'
2021-01-29 00:20:46 +05:30
it_behaves_like 'issues orderable by created_at'
2020-11-24 15:15:51 +05:30
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
2020-05-24 23:13:21 +05:30
before do
2020-11-24 15:15:51 +05:30
create(:issue, project: project, title: 'awesome opened issue')
create(:issue, :closed, project: project, title: 'awesome closed issue')
end
context 'state: opened' do
let(:state) { 'opened' }
include_examples 'filter by state', scope: :issues, search: 'awesome'
2020-05-24 23:13:21 +05:30
end
2020-11-24 15:15:51 +05:30
context 'state: closed' do
let(:state) { 'closed' }
include_examples 'filter by state', scope: :issues, search: 'awesome'
end
2020-05-24 23:13:21 +05:30
end
2021-01-03 14:25:43 +05:30
context 'filter by confidentiality' do
before do
create(:issue, project: project, author: user, title: 'awesome non-confidential issue')
create(:issue, :confidential, project: project, author: user, title: 'awesome confidential issue')
end
context 'confidential: true' do
let(:confidential) { true }
include_examples 'filter by confidentiality', scope: :issues, search: 'awesome'
end
context 'confidential: false' do
let(:confidential) { false }
include_examples 'filter by confidentiality', scope: :issues, search: 'awesome'
end
end
2018-03-17 18:26:18 +05:30
end
context 'for merge_requests scope' do
2020-11-24 15:15:51 +05:30
context 'without filtering by state' do
before do
create(:merge_request, source_project: repo_project, title: 'awesome mr')
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
get api(endpoint, user), params: { scope: 'merge_requests', search: 'awesome' }
end
it_behaves_like 'response is correct', schema: 'public_api/v4/merge_requests'
2018-03-17 18:26:18 +05:30
2020-11-24 15:15:51 +05:30
it_behaves_like 'ping counters', scope: :merge_requests
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'merge_requests', level: 'global'
2021-01-29 00:20:46 +05:30
it_behaves_like 'merge_requests orderable by created_at'
2020-11-24 15:15:51 +05:30
describe 'pagination' do
before do
create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch')
end
2020-05-24 23:13:21 +05:30
2020-11-24 15:15:51 +05:30
include_examples 'pagination', scope: :merge_requests
end
end
2020-06-23 00:09:42 +05:30
2020-11-24 15:15:51 +05:30
context 'filter by state' do
2020-05-24 23:13:21 +05:30
before do
2020-11-24 15:15:51 +05:30
create(:merge_request, source_project: project, title: 'awesome opened mr')
create(:merge_request, :closed, project: project, title: 'awesome closed mr')
2020-05-24 23:13:21 +05:30
end
2020-11-24 15:15:51 +05:30
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
2020-05-24 23:13:21 +05:30
end
2018-03-17 18:26:18 +05:30
end
context 'for milestones scope' do
before do
create(:milestone, project: project, title: 'awesome milestone')
2019-06-05 12:25:43 +05:30
end
context 'when user can read project milestones' do
before do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'milestones', search: 'awesome' }
2019-06-05 12:25:43 +05:30
end
2018-03-17 18:26:18 +05:30
2019-06-05 12:25:43 +05:30
it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :milestones
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'milestones', level: 'global'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:milestone, project: project, title: 'another milestone')
end
include_examples 'pagination', scope: :milestones
end
2018-03-17 18:26:18 +05:30
end
2019-06-05 12:25:43 +05:30
context 'when user cannot read project milestones' do
before do
project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
end
it 'returns empty array' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'milestones', search: 'awesome' }
2019-06-05 12:25:43 +05:30
2019-09-30 21:07:59 +05:30
milestones = json_response
2019-06-05 12:25:43 +05:30
expect(milestones).to be_empty
end
end
2018-03-17 18:26:18 +05:30
end
2019-07-07 11:18:12 +05:30
context 'for users scope' do
before do
create(:user, name: 'billy')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'users', search: 'billy' }
2019-07-07 11:18:12 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
2020-05-24 23:13:21 +05:30
it_behaves_like 'pagination', scope: :users
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :users
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'users', level: 'global'
2019-07-07 11:18:12 +05:30
end
2018-03-17 18:26:18 +05:30
context 'for snippet_titles scope' do
before do
create(:snippet, :public, title: 'awesome snippet', content: 'snippet content')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'snippet_titles', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/snippets'
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :snippet_titles
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'snippet_titles', level: 'global'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:snippet, :public, title: 'another snippet', content: 'snippet content')
end
2018-03-17 18:26:18 +05:30
2020-05-24 23:13:21 +05:30
include_examples 'pagination', scope: :snippet_titles
2018-03-17 18:26:18 +05:30
end
2023-03-17 16:20:25 +05:30
end
context 'global search is disabled for the given scope' do
it 'returns forbidden response' do
allow_next_instance_of(SearchService) do |instance|
allow(instance).to receive(:global_search_enabled_for_scope?).and_return false
end
get api(endpoint, user), params: { search: 'awesome', scope: 'issues' }
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'global search is enabled for the given scope' do
it 'returns forbidden response' do
allow_next_instance_of(SearchService) do |instance|
allow(instance).to receive(:global_search_enabled_for_scope?).and_return true
end
get api(endpoint, user), params: { search: 'awesome', scope: 'issues' }
expect(response).to have_gitlab_http_status(:ok)
end
2018-03-17 18:26:18 +05:30
end
2022-08-27 11:52:29 +05:30
2022-10-11 01:57:18 +05:30
it 'increments the custom search sli error rate with error false if no error occurred' do
expect(Gitlab::Metrics::GlobalSearchSlis).to receive(:record_error_rate).with(
error: false,
search_scope: 'issues',
search_type: 'basic',
search_level: 'global'
)
get api(endpoint, user), params: { scope: 'issues', search: 'john doe' }
end
it 'increments the custom search sli error rate with error true if an error occurred' do
allow_next_instance_of(SearchService) do |service|
allow(service).to receive(:search_results).and_raise(ActiveRecord::QueryCanceled)
end
expect(Gitlab::Metrics::GlobalSearchSlis).to receive(:record_error_rate).with(
error: true,
search_scope: 'issues',
search_type: 'basic',
search_level: 'global'
)
get api(endpoint, user), params: { scope: 'issues', search: 'john doe' }
end
2022-08-27 11:52:29 +05:30
it 'sets global search information for logging' do
expect(Gitlab::Instrumentation::GlobalSearchApi).to receive(:set_information).with(
type: 'basic',
level: 'global',
scope: 'issues',
search_duration_s: a_kind_of(Numeric)
)
get api(endpoint, user), params: { scope: 'issues', search: 'john doe' }
end
2018-03-17 18:26:18 +05:30
end
2022-03-02 08:16:31 +05:30
2022-05-07 20:08:51 +05:30
it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do
2022-03-02 08:16:31 +05:30
let(:current_user) { user }
def request
get api(endpoint, current_user), params: { scope: 'users', search: 'foo@bar.com' }
end
end
2018-03-17 18:26:18 +05:30
end
2018-05-09 12:01:36 +05:30
describe "GET /groups/:id/search" do
2020-05-24 23:13:21 +05:30
let(:endpoint) { "/groups/#{group.id}/-/search" }
2018-03-17 18:26:18 +05:30
context 'when user is not authenticated' do
it 'returns 401 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint), params: { scope: 'projects', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:unauthorized)
2018-03-17 18:26:18 +05:30
end
end
context 'when scope is not supported' do
it 'returns 400 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'unsupported', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:bad_request)
2018-03-17 18:26:18 +05:30
end
end
context 'when scope is missing' do
it 'returns 400 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:bad_request)
2018-03-17 18:26:18 +05:30
end
end
context 'when group does not exist' do
it 'returns 404 error' do
2019-07-07 11:18:12 +05:30
get api('/groups/0/search', user), params: { scope: 'issues', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2018-03-17 18:26:18 +05:30
end
end
context 'when user does can not see the group' do
it 'returns 404 error' do
private_group = create(:group, :private)
2019-02-15 15:39:39 +05:30
get api("/groups/#{private_group.id}/search", user), params: { scope: 'issues', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2018-03-17 18:26:18 +05:30
end
end
context 'with correct params' do
context 'for projects scope' do
before do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'projects', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/projects'
2020-05-24 23:13:21 +05:30
it_behaves_like 'pagination', scope: :projects
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :projects
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'projects', level: 'group'
2018-03-17 18:26:18 +05:30
end
context 'for issues scope' do
before do
create(:issue, project: project, title: 'awesome issue')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/issues'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :issues
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'issues', level: 'group'
2021-01-29 00:20:46 +05:30
it_behaves_like 'issues orderable by created_at'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:issue, project: project, title: 'another issue')
end
include_examples 'pagination', scope: :issues
end
2018-03-17 18:26:18 +05:30
end
context 'for merge_requests scope' do
before do
create(:merge_request, source_project: repo_project, title: 'awesome mr')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'merge_requests', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/merge_requests'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :merge_requests
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'merge_requests', level: 'group'
2021-01-29 00:20:46 +05:30
it_behaves_like 'merge_requests orderable by created_at'
2020-05-24 23:13:21 +05:30
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
2018-03-17 18:26:18 +05:30
end
context 'for milestones scope' do
before do
create(:milestone, project: project, title: 'awesome milestone')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'milestones', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :milestones
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'milestones', level: 'group'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:milestone, project: project, title: 'another milestone')
end
include_examples 'pagination', scope: :milestones
end
2018-03-17 18:26:18 +05:30
end
context 'for milestones scope with group path as id' do
before do
another_project = create(:project, :public)
create(:milestone, project: project, title: 'awesome milestone')
create(:milestone, project: another_project, title: 'awesome milestone other project')
2019-02-15 15:39:39 +05:30
get api("/groups/#{CGI.escape(group.full_path)}/search", user), params: { scope: 'milestones', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
end
2019-07-07 11:18:12 +05:30
context 'for users scope' do
before do
user = create(:user, name: 'billy')
create(:group_member, :developer, user: user, group: group)
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'users', search: 'billy' }
2019-07-07 11:18:12 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :users
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'users', level: 'group'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:group_member, :developer, group: group)
end
include_examples 'pagination', scope: :users
end
2019-07-07 11:18:12 +05:30
end
context 'for users scope with group path as id' do
before do
user1 = create(:user, name: 'billy')
create(:group_member, :developer, user: user1, group: group)
get api("/groups/#{CGI.escape(group.full_path)}/search", user), params: { scope: 'users', search: 'billy' }
end
it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
end
2022-03-02 08:16:31 +05:30
2022-05-07 20:08:51 +05:30
it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do
2022-03-02 08:16:31 +05:30
let(:current_user) { user }
def request
get api(endpoint, current_user), params: { scope: 'users', search: 'foo@bar.com' }
end
end
2018-03-17 18:26:18 +05:30
end
end
describe "GET /projects/:id/search" do
2020-05-24 23:13:21 +05:30
let(:endpoint) { "/projects/#{project.id}/search" }
2018-03-17 18:26:18 +05:30
context 'when user is not authenticated' do
it 'returns 401 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint), params: { scope: 'issues', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:unauthorized)
2018-03-17 18:26:18 +05:30
end
end
context 'when scope is not supported' do
it 'returns 400 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'unsupported', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:bad_request)
2018-03-17 18:26:18 +05:30
end
end
context 'when scope is missing' do
it 'returns 400 error' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:bad_request)
2018-03-17 18:26:18 +05:30
end
end
context 'when project does not exist' do
it 'returns 404 error' do
2019-07-07 11:18:12 +05:30
get api('/projects/0/search', user), params: { scope: 'issues', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2018-03-17 18:26:18 +05:30
end
end
2020-06-23 00:09:42 +05:30
context 'when user can not see the project' do
2018-03-17 18:26:18 +05:30
it 'returns 404 error' do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:not_found)
2018-03-17 18:26:18 +05:30
end
end
context 'with correct params' do
context 'for issues scope' do
before do
create(:issue, project: project, title: 'awesome issue')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/issues'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :issues
2021-01-29 00:20:46 +05:30
it_behaves_like 'issues orderable by created_at'
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'issues', level: 'project'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:issue, project: project, title: 'another issue')
end
include_examples 'pagination', scope: :issues
end
2018-03-17 18:26:18 +05:30
end
2021-01-29 00:20:46 +05:30
context 'when requesting basic search' do
it 'passes the parameter to search service' do
2022-10-11 01:57:18 +05:30
expect(SearchService).to receive(:new).with(user, hash_including(basic_search: 'true')).twice
2021-01-29 00:20:46 +05:30
get api(endpoint, user), params: { scope: 'issues', search: 'awesome', basic_search: 'true' }
end
end
2018-03-17 18:26:18 +05:30
context 'for merge_requests scope' do
2020-05-24 23:13:21 +05:30
let(:endpoint) { "/projects/#{repo_project.id}/search" }
2018-03-17 18:26:18 +05:30
before do
create(:merge_request, source_project: repo_project, title: 'awesome mr')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'merge_requests', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/merge_requests'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :merge_requests
2021-01-29 00:20:46 +05:30
it_behaves_like 'merge_requests orderable by created_at'
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'merge_requests', level: 'project'
2020-05-24 23:13:21 +05:30
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
2018-03-17 18:26:18 +05:30
end
context 'for milestones scope' do
before do
create(:milestone, project: project, title: 'awesome milestone')
2019-06-05 12:25:43 +05:30
end
context 'when user can read milestones' do
before do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'milestones', search: 'awesome' }
2019-06-05 12:25:43 +05:30
end
2018-03-17 18:26:18 +05:30
2019-06-05 12:25:43 +05:30
it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :milestones
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'milestones', level: 'project'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:milestone, project: project, title: 'another milestone')
end
include_examples 'pagination', scope: :milestones
end
2018-03-17 18:26:18 +05:30
end
2019-06-05 12:25:43 +05:30
context 'when user cannot read project milestones' do
before do
project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
end
it 'returns empty array' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'milestones', search: 'awesome' }
2019-06-05 12:25:43 +05:30
2019-09-30 21:07:59 +05:30
milestones = json_response
2019-06-05 12:25:43 +05:30
expect(milestones).to be_empty
end
end
2018-03-17 18:26:18 +05:30
end
2019-07-07 11:18:12 +05:30
context 'for users scope' do
before do
user1 = create(:user, name: 'billy')
create(:project_member, :developer, user: user1, project: project)
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'users', search: 'billy' }
2019-07-07 11:18:12 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :users
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'users', level: 'project'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:project_member, :developer, project: project)
end
include_examples 'pagination', scope: :users
end
2019-07-07 11:18:12 +05:30
end
2018-03-17 18:26:18 +05:30
context 'for notes scope' do
before do
create(:note_on_merge_request, project: project, note: 'awesome note')
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'notes', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/notes'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :notes
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'notes', level: 'project'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
mr = create(:merge_request, source_project: project, target_branch: 'another_branch')
create(:note, project: project, noteable: mr, note: 'another note')
end
include_examples 'pagination', scope: :notes
end
2018-03-17 18:26:18 +05:30
end
context 'for wiki_blobs scope' do
2020-05-24 23:13:21 +05:30
let(:wiki) { create(:project_wiki, project: project) }
2018-03-17 18:26:18 +05:30
before do
2020-05-24 23:13:21 +05:30
create(:wiki_page, wiki: wiki, title: 'home', content: "Awesome page")
2018-03-17 18:26:18 +05:30
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'wiki_blobs', search: 'awesome' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/blobs'
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :wiki_blobs
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'wiki_blobs', level: 'project'
2020-05-24 23:13:21 +05:30
describe 'pagination' do
before do
create(:wiki_page, wiki: wiki, title: 'home 2', content: 'Another page')
end
include_examples 'pagination', scope: :wiki_blobs, search: 'page'
end
2018-03-17 18:26:18 +05:30
end
context 'for commits scope' do
2020-05-24 23:13:21 +05:30
let(:endpoint) { "/projects/#{repo_project.id}/search" }
2018-03-17 18:26:18 +05:30
before do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'commits', search: '498214de67004b1da3d820901307bed2a68a8ef6' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/commits_details'
2020-05-24 23:13:21 +05:30
it_behaves_like 'pagination', scope: :commits, search: 'merge'
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :commits
2022-09-01 20:07:04 +05:30
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'commits', level: 'project'
2022-09-01 20:07:04 +05:30
describe 'pipeline visibility' do
shared_examples 'pipeline information visible' do
it 'contains status and last_pipeline' do
request
expect(json_response[0]['status']).to eq 'success'
expect(json_response[0]['last_pipeline']).not_to be_nil
end
end
shared_examples 'pipeline information not visible' do
it 'does not contain status and last_pipeline' do
request
expect(json_response[0]['status']).to be_nil
expect(json_response[0]['last_pipeline']).to be_nil
end
end
let(:request) { get api(endpoint, user), params: { scope: 'commits', search: repo_project.commit.sha } }
before do
create(:ci_pipeline, :success, project: repo_project, sha: repo_project.commit.sha)
end
context 'with non public pipeline' do
let_it_be(:repo_project) do
create(:project, :public, :repository, public_builds: false, group: group)
end
context 'user is project member with reporter role or above' do
before do
repo_project.add_reporter(user)
end
it_behaves_like 'pipeline information visible'
end
context 'user is project member with guest role' do
before do
repo_project.add_guest(user)
end
it_behaves_like 'pipeline information not visible'
end
context 'user is not project member' do
let_it_be(:user) { create(:user) }
it_behaves_like 'pipeline information not visible'
end
end
context 'with public pipeline' do
let_it_be(:repo_project) do
create(:project, :public, :repository, public_builds: true, group: group)
end
context 'user is project member with reporter role or above' do
before do
repo_project.add_reporter(user)
end
it_behaves_like 'pipeline information visible'
end
context 'user is project member with guest role' do
before do
repo_project.add_guest(user)
end
it_behaves_like 'pipeline information visible'
end
context 'user is not project member' do
let_it_be(:user) { create(:user) }
it_behaves_like 'pipeline information visible'
context 'when CI/CD is set to only project members' do
before do
repo_project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
end
it_behaves_like 'pipeline information not visible'
end
end
end
end
2018-03-17 18:26:18 +05:30
end
context 'for commits scope with project path as id' do
before do
2019-02-15 15:39:39 +05:30
get api("/projects/#{CGI.escape(repo_project.full_path)}/search", user), params: { scope: 'commits', search: '498214de67004b1da3d820901307bed2a68a8ef6' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/commits_details'
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'commits', level: 'project'
2018-03-17 18:26:18 +05:30
end
context 'for blobs scope' do
2020-05-24 23:13:21 +05:30
let(:endpoint) { "/projects/#{repo_project.id}/search" }
2018-03-17 18:26:18 +05:30
before do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'blobs', search: 'monitors' }
2018-03-17 18:26:18 +05:30
end
it_behaves_like 'response is correct', schema: 'public_api/v4/blobs', size: 2
2018-11-08 19:23:39 +05:30
2020-05-24 23:13:21 +05:30
it_behaves_like 'pagination', scope: :blobs, search: 'monitors'
2020-06-23 00:09:42 +05:30
it_behaves_like 'ping counters', scope: :blobs
2023-01-13 00:05:48 +05:30
it_behaves_like 'apdex recorded', scope: 'blobs', level: 'project'
2018-11-08 19:23:39 +05:30
context 'filters' do
it 'by filename' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'blobs', search: 'mon filename:PROCESS.md' }
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:ok)
2018-11-08 19:23:39 +05:30
expect(json_response.size).to eq(2)
2019-12-26 22:10:19 +05:30
expect(json_response.first['path']).to eq('PROCESS.md')
2018-11-08 19:23:39 +05:30
expect(json_response.first['filename']).to eq('PROCESS.md')
end
it 'by path' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'blobs', search: 'mon path:markdown' }
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:ok)
2018-11-08 19:23:39 +05:30
expect(json_response.size).to eq(8)
end
it 'by extension' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'blobs', search: 'mon extension:md' }
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:ok)
2018-11-08 19:23:39 +05:30
expect(json_response.size).to eq(11)
end
2019-09-04 21:01:54 +05:30
it 'by ref' do
2020-05-24 23:13:21 +05:30
get api(endpoint, user), params: { scope: 'blobs', search: 'This file is used in tests for ci_environments_status', ref: 'pages-deploy' }
2019-09-04 21:01:54 +05:30
2020-04-08 14:13:33 +05:30
expect(response).to have_gitlab_http_status(:ok)
2019-09-04 21:01:54 +05:30
expect(json_response.size).to eq(1)
end
2018-11-08 19:23:39 +05:30
end
2018-03-17 18:26:18 +05:30
end
2022-03-02 08:16:31 +05:30
2022-05-07 20:08:51 +05:30
it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do
2022-03-02 08:16:31 +05:30
let(:current_user) { user }
def request
get api(endpoint, current_user), params: { scope: 'users', search: 'foo@bar.com' }
end
end
2018-03-17 18:26:18 +05:30
end
end
end