Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/api/graphql/issues_spec.rb')
-rw-r--r--spec/requests/api/graphql/issues_spec.rb128
1 files changed, 103 insertions, 25 deletions
diff --git a/spec/requests/api/graphql/issues_spec.rb b/spec/requests/api/graphql/issues_spec.rb
index 8838ad78f72..ba6f8ec2cab 100644
--- a/spec/requests/api/graphql/issues_spec.rb
+++ b/spec/requests/api/graphql/issues_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'getting an issue list at root level' do
+RSpec.describe 'getting an issue list at root level', feature_category: :team_planning do
include GraphqlHelpers
let_it_be(:developer) { create(:user) }
@@ -13,34 +13,81 @@ RSpec.describe 'getting an issue list at root level' do
let_it_be(:project_b) { create(:project, :repository, :private, group: group1) }
let_it_be(:project_c) { create(:project, :repository, :public, group: group2) }
let_it_be(:project_d) { create(:project, :repository, :private, group: group2) }
- let_it_be(:early_milestone) { create(:milestone, project: project_d, due_date: 10.days.from_now) }
- let_it_be(:late_milestone) { create(:milestone, project: project_c, due_date: 30.days.from_now) }
+ let_it_be(:milestone1) { create(:milestone, project: project_c, due_date: 10.days.from_now) }
+ let_it_be(:milestone2) { create(:milestone, project: project_d, due_date: 20.days.from_now) }
+ let_it_be(:milestone3) { create(:milestone, project: project_d, due_date: 30.days.from_now) }
+ let_it_be(:milestone4) { create(:milestone, project: project_a, due_date: 40.days.from_now) }
let_it_be(:priority1) { create(:label, project: project_c, priority: 1) }
let_it_be(:priority2) { create(:label, project: project_d, priority: 5) }
let_it_be(:priority3) { create(:label, project: project_a, priority: 10) }
+ let_it_be(:priority4) { create(:label, project: project_d, priority: 15) }
+
+ let_it_be(:issue_a) do
+ create(
+ :issue,
+ project: project_a,
+ labels: [priority3],
+ due_date: 1.day.ago,
+ milestone: milestone4,
+ relative_position: 1000
+ )
+ end
+
+ let_it_be(:issue_b) do
+ create(
+ :issue,
+ :with_alert,
+ project: project_b,
+ discussion_locked: true,
+ due_date: 1.day.from_now,
+ relative_position: 3000
+ )
+ end
- let_it_be(:issue_a) { create(:issue, project: project_a, labels: [priority3]) }
- let_it_be(:issue_b) { create(:issue, :with_alert, project: project_b, discussion_locked: true) }
let_it_be(:issue_c) do
create(
:issue,
+ :confidential,
project: project_c,
title: 'title matching issue plus',
labels: [priority1],
- milestone: late_milestone
+ milestone: milestone1,
+ due_date: 3.days.from_now,
+ relative_position: nil
)
end
- let_it_be(:issue_d) { create(:issue, :with_alert, project: project_d, discussion_locked: true, labels: [priority2]) }
- let_it_be(:issue_e) { create(:issue, project: project_d, milestone: early_milestone) }
+ let_it_be(:issue_d) do
+ create(
+ :issue,
+ :with_alert,
+ project: project_d,
+ discussion_locked: true,
+ labels: [priority2],
+ milestone: milestone3,
+ relative_position: 5000
+ )
+ end
- let(:issue_filter_params) { {} }
+ let_it_be(:issue_e) do
+ create(
+ :issue,
+ :confidential,
+ project: project_d,
+ milestone: milestone2,
+ due_date: 3.days.ago,
+ relative_position: nil,
+ labels: [priority2, priority4]
+ )
+ end
+ let_it_be(:issues, reload: true) { [issue_a, issue_b, issue_c, issue_d, issue_e] }
+
+ let(:issue_filter_params) { {} }
+ let(:current_user) { developer }
let(:fields) do
<<~QUERY
- nodes {
- #{all_graphql_fields_for('issues'.classify)}
- }
+ nodes { id }
QUERY
end
@@ -60,13 +107,16 @@ RSpec.describe 'getting an issue list at root level' do
end
end
+ # All new specs should be added to the shared example if the change also
+ # affects the `issues` query at the root level of the API.
+ # Shared example also used in spec/requests/api/graphql/project/issues_spec.rb
it_behaves_like 'graphql issue list request spec' do
- subject(:post_query) { post_graphql(query, current_user: current_user) }
+ let_it_be(:external_user) { create(:user) }
+
+ let(:public_projects) { [project_a, project_c] }
- let(:current_user) { developer }
let(:another_user) { reporter }
- let(:issues_data) { graphql_data['issues']['nodes'] }
- let(:issue_ids) { graphql_dig_at(issues_data, :id) }
+ let(:issue_nodes_path) { %w[issues nodes] }
# filters
let(:expected_negated_assignee_issues) { [issue_b, issue_c, issue_d, issue_e] }
@@ -77,12 +127,25 @@ RSpec.describe 'getting an issue list at root level' do
let(:unlocked_discussion_issues) { [issue_a, issue_c, issue_e] }
let(:search_title_term) { 'matching issue' }
let(:title_search_issue) { issue_c }
+ let(:confidential_issues) { [issue_c, issue_e] }
+ let(:non_confidential_issues) { [issue_a, issue_b, issue_d] }
+ let(:public_non_confidential_issues) { [issue_a] }
# sorting
let(:data_path) { [:issues] }
- let(:expected_severity_sorted_asc) { [issue_c, issue_a, issue_b, issue_e, issue_d] }
- let(:expected_priority_sorted_asc) { [issue_e, issue_c, issue_d, issue_a, issue_b] }
- let(:expected_priority_sorted_desc) { [issue_c, issue_e, issue_a, issue_d, issue_b] }
+ let(:expected_priority_sorted_asc) { [issue_c, issue_e, issue_d, issue_a, issue_b] }
+ let(:expected_priority_sorted_desc) { [issue_a, issue_d, issue_e, issue_c, issue_b] }
+ let(:expected_due_date_sorted_desc) { [issue_c, issue_b, issue_a, issue_e, issue_d] }
+ let(:expected_due_date_sorted_asc) { [issue_e, issue_a, issue_b, issue_c, issue_d] }
+ let(:expected_relative_position_sorted_asc) { [issue_a, issue_b, issue_d, issue_c, issue_e] }
+ let(:expected_label_priority_sorted_asc) { [issue_c, issue_e, issue_d, issue_a, issue_b] }
+ let(:expected_label_priority_sorted_desc) { [issue_a, issue_e, issue_d, issue_c, issue_b] }
+ let(:expected_milestone_sorted_asc) { [issue_c, issue_e, issue_d, issue_a, issue_b] }
+ let(:expected_milestone_sorted_desc) { [issue_a, issue_d, issue_e, issue_c, issue_b] }
+
+ # N+1 queries
+ let(:same_project_issue1) { issue_d }
+ let(:same_project_issue2) { issue_e }
before_all do
issue_a.assignee_ids = developer.id
@@ -90,12 +153,6 @@ RSpec.describe 'getting an issue list at root level' do
create(:award_emoji, :upvote, user: developer, awardable: issue_a)
create(:award_emoji, :upvote, user: developer, awardable: issue_c)
-
- # severity sorting
- create(:issuable_severity, issue: issue_a, severity: :unknown)
- create(:issuable_severity, issue: issue_b, severity: :low)
- create(:issuable_severity, issue: issue_d, severity: :critical)
- create(:issuable_severity, issue: issue_e, severity: :high)
end
def pagination_query(params)
@@ -107,6 +164,27 @@ RSpec.describe 'getting an issue list at root level' do
end
end
+ context 'when fetching issues from multiple projects' do
+ it 'avoids N+1 queries' do
+ post_query # warm-up
+
+ control = ActiveRecord::QueryRecorder.new { post_query }
+
+ new_private_project = create(:project, :private).tap { |project| project.add_developer(current_user) }
+ create(:issue, project: new_private_project)
+
+ expect { post_query }.not_to exceed_query_limit(control)
+ end
+ end
+
+ def execute_query
+ post_query
+ end
+
+ def post_query(request_user = current_user)
+ post_graphql(query, current_user: request_user)
+ end
+
def query(params = issue_filter_params)
graphql_query_for(
:issues,