1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::GroupMilestones, feature_category: :team_planning do
let_it_be(:user) { create(:user) }
let_it_be_with_refind(:group) { create(:group, :private) }
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:group_member) { create(:group_member, group: group, user: user) }
let_it_be(:closed_milestone) do
create(:closed_milestone, group: group, title: 'version1', description: 'closed milestone')
end
let_it_be_with_reload(:milestone) do
create(:milestone, group: group, title: 'version2', description: 'open milestone', updated_at: 4.days.ago)
end
let(:route) { "/groups/#{group.id}/milestones" }
shared_examples 'listing all milestones' do
it 'returns correct list of milestones' do
get api(route, user), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.size).to eq(milestones.size)
expect(json_response.map { |entry| entry["id"] }).to eq(milestones.map(&:id))
end
end
it_behaves_like 'group and project milestones', "/groups/:id/milestones"
describe 'GET /groups/:id/milestones' do
context 'for REST only' do
let_it_be(:ancestor_group) { create(:group, :private) }
let_it_be(:ancestor_group_milestone) { create(:milestone, group: ancestor_group, updated_at: 2.days.ago) }
before_all do
group.update!(parent: ancestor_group)
end
context 'when include_ancestors is true' do
let(:params) { { include_ancestors: true } }
context 'when user has access to ancestor groups' do
let(:milestones) { [ancestor_group_milestone, milestone, closed_milestone] }
before do
ancestor_group.add_guest(user)
group.add_guest(user)
end
it_behaves_like 'listing all milestones'
context 'when deprecated include_parent_milestones is true' do
let(:params) { { include_parent_milestones: true } }
it_behaves_like 'listing all milestones'
end
context 'when both include_parent_milestones and include_ancestors are specified' do
let(:params) { { include_ancestors: true, include_parent_milestones: true } }
it 'returns 400' do
get api(route, user), params: params
expect(response).to have_gitlab_http_status(:bad_request)
end
end
context 'when iids param is present' do
let(:params) { { include_ancestors: true, iids: [milestone.iid] } }
it_behaves_like 'listing all milestones'
end
context 'when updated_before param is present' do
let(:params) { { updated_before: 1.day.ago.iso8601, include_ancestors: true } }
it_behaves_like 'listing all milestones' do
let(:milestones) { [ancestor_group_milestone, milestone] }
end
end
context 'when updated_after param is present' do
let(:params) { { updated_after: 1.day.ago.iso8601, include_ancestors: true } }
it_behaves_like 'listing all milestones' do
let(:milestones) { [closed_milestone] }
end
end
end
context 'when user has no access to ancestor groups' do
let(:user) { create(:user) }
before do
group.add_guest(user)
end
it_behaves_like 'listing all milestones' do
let(:milestones) { [milestone, closed_milestone] }
end
end
end
context 'when updated_before param is present' do
let(:params) { { updated_before: 1.day.ago.iso8601 } }
it_behaves_like 'listing all milestones' do
let(:milestones) { [milestone] }
end
end
context 'when updated_after param is present' do
let(:params) { { updated_after: 1.day.ago.iso8601 } }
it_behaves_like 'listing all milestones' do
let(:milestones) { [closed_milestone] }
end
end
end
context 'for common GraphQL/REST' do
it_behaves_like 'group milestones including ancestors and descendants'
def query_group_milestone_ids(params)
get api(route, current_user), params: params
json_response.pluck('id')
end
end
end
describe 'GET /groups/:id/milestones/:milestone_id/issues' do
let!(:issue) { create(:issue, project: project, milestone: milestone) }
def perform_request
get api("/groups/#{group.id}/milestones/#{milestone.id}/issues", user)
end
it 'returns multiple issues without performing N + 1' do
perform_request
control_count = ActiveRecord::QueryRecorder.new { perform_request }.count
create(:issue, project: project, milestone: milestone)
expect { perform_request }.not_to exceed_query_limit(control_count)
end
end
def setup_for_group
context_group.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
context_group.add_reporter(user)
public_project.update!(namespace: context_group)
context_group.reload
end
end
|