Read about our upcoming Code of Conduct on this issue

merge_requests_finder_spec.rb 14.3 KB
Newer Older
1
2
3
require 'spec_helper'

describe MergeRequestsFinder do
4
  context "multiple projects with merge requests" do
5
    include_context 'MergeRequestsFinder multiple projects with merge requests context'
6

7
8
9
    describe '#execute' do
      it 'filters by scope' do
        params = { scope: 'authored', state: 'opened' }
10

11
        merge_requests = described_class.new(user, params).execute
12
13

        expect(merge_requests).to contain_exactly(merge_request1, merge_request4, merge_request5)
14
      end
15

16
17
      it 'filters by project' do
        params = { project_id: project1.id, scope: 'authored', state: 'opened' }
18

19
        merge_requests = described_class.new(user, params).execute
20
21

        expect(merge_requests).to contain_exactly(merge_request1)
22
      end
23

24
25
26
27
28
29
30
31
32
33
      it 'filters by commit sha' do
        merge_requests = described_class.new(
          user,
          commit_sha: merge_request5.merge_request_diff.last_commit_sha
        ).execute

        expect(merge_requests).to contain_exactly(merge_request5)
      end

      context 'filtering by group' do
34
        it 'includes all merge requests when user has access excluding merge requests from projects the user does not have access to' do
35
36
          private_project = allow_gitaly_n_plus_1 { create(:project, :private, group: group) }
          private_project.add_guest(user)
37
          create(:merge_request, :simple, author: user, source_project: private_project, target_project: private_project)
38
39
40
41
          params = { group_id: group.id }

          merge_requests = described_class.new(user, params).execute

42
          expect(merge_requests).to contain_exactly(merge_request1, merge_request2)
43
44
45
46
47
48
49
        end

        it 'filters by group including subgroups', :nested_groups do
          params = { group_id: group.id, include_subgroups: true }

          merge_requests = described_class.new(user, params).execute

50
          expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request5)
51
52
53
54
55
        end
      end

      it 'filters by non_archived' do
        params = { non_archived: true }
56

57
        merge_requests = described_class.new(user, params).execute
58
59

        expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request5)
60
61
62
63
      end

      it 'filters by iid' do
        params = { project_id: project1.id, iids: merge_request1.iid }
64

65
        merge_requests = described_class.new(user, params).execute
66

67
        expect(merge_requests).to contain_exactly(merge_request1)
68
      end
69

70
71
      it 'filters by source branch' do
        params = { source_branch: merge_request2.source_branch }
72

73
74
        merge_requests = described_class.new(user, params).execute

75
        expect(merge_requests).to contain_exactly(merge_request2)
76
77
      end

78
79
      it 'filters by target branch' do
        params = { target_branch: merge_request2.target_branch }
80
81

        merge_requests = described_class.new(user, params).execute
82

83
        expect(merge_requests).to contain_exactly(merge_request2)
84
      end
85

86
87
88
89
90
91
92
93
      it 'filters by source project id' do
        params = { source_project_id: merge_request2.source_project_id }

        merge_requests = described_class.new(user, params).execute

        expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3)
      end

94
95
      it 'filters by state' do
        params = { state: 'locked' }
mhasbini's avatar
mhasbini committed
96

97
        merge_requests = described_class.new(user, params).execute
mhasbini's avatar
mhasbini committed
98

99
100
        expect(merge_requests).to contain_exactly(merge_request3)
      end
mhasbini's avatar
mhasbini committed
101

102
103
104
105
106
      describe 'WIP state' do
        let!(:wip_merge_request1) { create(:merge_request, :simple, author: user, source_project: project5, target_project: project5, title: 'WIP: thing') }
        let!(:wip_merge_request2) { create(:merge_request, :simple, author: user, source_project: project6, target_project: project6, title: 'wip thing') }
        let!(:wip_merge_request3) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project1, title: '[wip] thing') }
        let!(:wip_merge_request4) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2, title: 'wip: thing') }
107

108
109
        it 'filters by wip' do
          params = { wip: 'yes' }
110

111
          merge_requests = described_class.new(user, params).execute
112

113
114
          expect(merge_requests).to contain_exactly(merge_request4, merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4)
        end
115

116
117
        it 'filters by not wip' do
          params = { wip: 'no' }
118

119
          merge_requests = described_class.new(user, params).execute
120

121
122
          expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3)
        end
123

124
125
        it 'returns all items if no valid wip param exists' do
          params = { wip: '' }
126

127
          merge_requests = described_class.new(user, params).execute
128

129
130
131
132
133
          expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4)
        end

        it 'adds wip to scalar params' do
          scalar_params = described_class.scalar_params
134

135
136
          expect(scalar_params).to include(:wip, :assignee_id)
        end
137
      end
138

139
140
      context 'assignee filtering' do
        let(:issuables) { described_class.new(user, params).execute }
141

142
143
144
        it_behaves_like 'assignee ID filter' do
          let(:params) { { assignee_id: user.id } }
          let(:expected_issuables) { [merge_request1, merge_request2] }
145
        end
146

147
148
149
150
151
        it_behaves_like 'assignee username filter' do
          before do
            project2.add_developer(user3)
            merge_request3.assignees = [user2, user3]
          end
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
          set(:user3) { create(:user) }
          let(:params) { { assignee_username: [user2.username, user3.username] } }
          let(:expected_issuables) { [merge_request3] }
        end

        it_behaves_like 'no assignee filter' do
          set(:user3) { create(:user) }
          let(:expected_issuables) { [merge_request4, merge_request5] }
        end

        it_behaves_like 'any assignee filter' do
          let(:expected_issuables) { [merge_request1, merge_request2, merge_request3] }
        end

        context 'filtering by group milestone' do
          let(:group_milestone) { create(:milestone, group: group) }

          before do
            project2.update(namespace: group)
            merge_request2.update(milestone: group_milestone)
            merge_request3.update(milestone: group_milestone)
          end

          it 'returns merge requests assigned to that group milestone' do
            params = { milestone_title: group_milestone.title }

            merge_requests = described_class.new(user, params).execute
180

181
182
            expect(merge_requests).to contain_exactly(merge_request2, merge_request3)
          end
183
184
        end
      end
185

186
187
      context 'filtering by created_at/updated_at' do
        let(:new_project) { create(:project, forked_from_project: project1) }
188

189
190
191
192
193
194
195
196
197
        let!(:new_merge_request) do
          create(:merge_request,
                :simple,
                author: user,
                created_at: 1.week.from_now,
                updated_at: 1.week.from_now,
                source_project: new_project,
                target_project: new_project)
        end
198

199
200
201
202
203
204
205
206
207
208
        let!(:old_merge_request) do
          create(:merge_request,
                :simple,
                author: user,
                source_branch: 'feature_1',
                created_at: 1.week.ago,
                updated_at: 1.week.ago,
                source_project: new_project,
                target_project: new_project)
        end
209

210
211
212
        before do
          new_project.add_maintainer(user)
        end
213

214
215
        it 'filters by created_after' do
          params = { project_id: new_project.id, created_after: new_merge_request.created_at }
216

217
          merge_requests = described_class.new(user, params).execute
218

219
220
          expect(merge_requests).to contain_exactly(new_merge_request)
        end
Felipe Artur's avatar
Felipe Artur committed
221

222
223
        it 'filters by created_before' do
          params = { project_id: new_project.id, created_before: old_merge_request.created_at }
Felipe Artur's avatar
Felipe Artur committed
224

225
          merge_requests = described_class.new(user, params).execute
Felipe Artur's avatar
Felipe Artur committed
226

227
228
          expect(merge_requests).to contain_exactly(old_merge_request)
        end
Felipe Artur's avatar
Felipe Artur committed
229

230
231
232
233
234
235
        it 'filters by created_after and created_before' do
          params = {
            project_id: new_project.id,
            created_after: old_merge_request.created_at,
            created_before: new_merge_request.created_at
          }
236

237
          merge_requests = described_class.new(user, params).execute
238

239
240
          expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
        end
241

242
243
        it 'filters by updated_after' do
          params = { project_id: new_project.id, updated_after: new_merge_request.updated_at }
244

245
          merge_requests = described_class.new(user, params).execute
246

247
248
          expect(merge_requests).to contain_exactly(new_merge_request)
        end
249

250
251
        it 'filters by updated_before' do
          params = { project_id: new_project.id, updated_before: old_merge_request.updated_at }
252

253
          merge_requests = described_class.new(user, params).execute
254

255
256
          expect(merge_requests).to contain_exactly(old_merge_request)
        end
257

258
259
260
261
262
263
        it 'filters by updated_after and updated_before' do
          params = {
            project_id: new_project.id,
            updated_after: old_merge_request.updated_at,
            updated_before: new_merge_request.updated_at
          }
264

265
          merge_requests = described_class.new(user, params).execute
266

267
268
          expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
        end
269
      end
270
    end
271

272
273
274
    describe '#row_count', :request_store do
      it 'returns the number of rows for the default state' do
        finder = described_class.new(user)
275

276
        expect(finder.row_count).to eq(3)
277
278
279
280
      end

      it 'returns the number of rows for a given state' do
        finder = described_class.new(user, state: 'closed')
281

282
        expect(finder.row_count).to eq(1)
283
      end
284
    end
285
286
287
288
289
290
291

    context 'external authorization' do
      it_behaves_like 'a finder with external authorization service' do
        let!(:subject) { create(:merge_request, source_project: project) }
        let(:project_params) { { project_id: project.id } }
      end
    end
292
  end
293

294
295
  context 'when projects require different access levels for merge requests' do
    let(:user) { create(:user) }
296

297
298
299
300
301
    let(:public_project) { create(:project, :public) }
    let(:internal) { create(:project, :internal) }
    let(:private_project) { create(:project, :private) }
    let(:public_with_private_repo) { create(:project, :public, :repository, :repository_private) }
    let(:internal_with_private_repo) { create(:project, :internal, :repository, :repository_private) }
302

303
    let(:merge_requests) { described_class.new(user, {}).execute }
304

305
306
307
308
309
    let!(:mr_public) { create(:merge_request, source_project: public_project) }
    let!(:mr_private) { create(:merge_request, source_project: private_project) }
    let!(:mr_internal) { create(:merge_request, source_project: internal) }
    let!(:mr_private_repo_access) { create(:merge_request, source_project: public_with_private_repo) }
    let!(:mr_internal_private_repo_access) { create(:merge_request, source_project: internal_with_private_repo) }
310

311
312
    context 'with admin user' do
      let(:user) { create(:user, :admin) }
313

314
315
316
317
      it 'returns all merge requests' do
        expect(merge_requests).to eq(
          [mr_internal_private_repo_access, mr_private_repo_access, mr_internal, mr_private, mr_public]
        )
318
      end
319
    end
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

    context 'when project restricts merge requests' do
      let(:non_member) { create(:user) }
      let(:project) { create(:project, :repository, :public, :merge_requests_private) }
      let!(:merge_request) { create(:merge_request, source_project: project) }

      it "returns nothing to to non members" do
        merge_requests = described_class.new(
          non_member,
          project_id: project.id
        ).execute

        expect(merge_requests).to be_empty
      end
    end
335

336
337
    context 'with external user' do
      let(:user) { create(:user, :external) }
338

339
340
341
      it 'returns only public merge requests' do
        expect(merge_requests).to eq([mr_public])
      end
342
343
    end

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
    context 'with authenticated user' do
      it 'returns public and internal merge requests' do
        expect(merge_requests).to eq([mr_internal, mr_public])
      end

      context 'being added to the private project' do
        context 'as a guest' do
          before do
            private_project.add_guest(user)
          end

          it 'does not return merge requests from the private project' do
            expect(merge_requests).to eq([mr_internal, mr_public])
          end
        end

        context 'as a developer' do
          before do
            private_project.add_developer(user)
          end

          it 'returns merge requests from the private project' do
            expect(merge_requests).to eq([mr_internal, mr_private, mr_public])
          end
        end
      end
370

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
      context 'being added to the public project with private repo access' do
        context 'as a guest' do
          before do
            public_with_private_repo.add_guest(user)
          end

          it 'returns merge requests from the project' do
            expect(merge_requests).to eq([mr_internal, mr_public])
          end
        end

        context 'as a reporter' do
          before do
            public_with_private_repo.add_reporter(user)
          end

          it 'returns merge requests from the project' do
            expect(merge_requests).to eq([mr_private_repo_access, mr_internal, mr_public])
          end
        end
      end

      context 'being added to the internal project with private repo access' do
        context 'as a guest' do
          before do
            internal_with_private_repo.add_guest(user)
          end

          it 'returns merge requests from the project' do
            expect(merge_requests).to eq([mr_internal, mr_public])
          end
        end

        context 'as a reporter' do
          before do
            internal_with_private_repo.add_reporter(user)
          end

          it 'returns merge requests from the project' do
            expect(merge_requests).to eq([mr_internal_private_repo_access, mr_internal, mr_public])
          end
        end
      end
414
415
    end
  end
416
end