merge_requests_spec.rb 47.3 KB
Newer Older
V
Valeriy Sizov 已提交
1 2
require "spec_helper"

3
describe API::MergeRequests do
B
Bob Van Landuyt 已提交
4 5
  include ProjectForksHelper

Z
Zeger-Jan van de Weg 已提交
6 7 8
  let(:base_time)   { Time.now }
  let(:user)        { create(:user) }
  let(:admin)       { create(:user, :admin) }
9
  let(:non_member)  { create(:user) }
10
  let!(:project)    { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
Z
Zeger-Jan van de Weg 已提交
11
  let(:milestone)   { create(:milestone, title: '1.0.0', project: project) }
12 13 14 15 16 17 18 19 20
  let(:milestone1)   { create(:milestone, title: '0.9', project: project) }
  let!(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time) }
  let!(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
  let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
  let!(:note)       { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
  let!(:note2)      { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
  let!(:label) do
    create(:label, title: 'label', color: '#FFAABB', project: project)
  end
21
  let!(:label2) { create(:label, title: 'a-test', color: '#FFFFFF', project: project) }
22
  let!(:label_link) { create(:label_link, label: label, target: merge_request) }
23 24 25
  let!(:label_link2) { create(:label_link, label: label2, target: merge_request) }
  let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request) }
  let!(:upvote) { create(:award_emoji, :upvote, awardable: merge_request) }
26 27

  before do
28
    project.team << [user, :reporter]
29
  end
V
Valeriy Sizov 已提交
30

31 32
  describe 'GET /merge_requests' do
    context 'when unauthenticated' do
33 34 35
      it 'returns an array of all merge requests' do
        get api('/merge_requests', user), scope: 'all'

36
        expect(response).to have_gitlab_http_status(200)
37 38 39 40 41 42
        expect(json_response).to be_an Array
      end

      it "returns authentication error without any scope" do
        get api("/merge_requests")

43
        expect(response).to have_gitlab_http_status(401)
44 45 46 47
      end

      it "returns authentication error  when scope is assigned-to-me" do
        get api("/merge_requests"), scope: 'assigned-to-me'
48

49
        expect(response).to have_gitlab_http_status(401)
50 51 52 53 54
      end

      it "returns authentication error  when scope is created-by-me" do
        get api("/merge_requests"), scope: 'created-by-me'

55
        expect(response).to have_gitlab_http_status(401)
56 57 58 59
      end
    end

    context 'when authenticated' do
60
      let!(:project2) { create(:project, :public, namespace: user.namespace) }
61 62 63 64
      let!(:merge_request2) { create(:merge_request, :simple, author: user, assignee: user, source_project: project2, target_project: project2) }
      let(:user2) { create(:user) }

      it 'returns an array of all merge requests' do
65
        get api('/merge_requests', user), scope: :all
66

L
Lin Jen-Shin 已提交
67
        expect(response).to have_gitlab_http_status(200)
68 69 70 71 72 73 74
        expect(response).to include_pagination_headers
        expect(json_response).to be_an Array
        expect(json_response.map { |mr| mr['id'] })
          .to contain_exactly(merge_request.id, merge_request_closed.id, merge_request_merged.id, merge_request2.id)
      end

      it 'does not return unauthorized merge requests' do
75
        private_project = create(:project, :private)
76 77
        merge_request3 = create(:merge_request, :simple, source_project: private_project, target_project: private_project, source_branch: 'other-branch')

78
        get api('/merge_requests', user), scope: :all
79

L
Lin Jen-Shin 已提交
80
        expect(response).to have_gitlab_http_status(200)
81 82 83 84 85 86
        expect(response).to include_pagination_headers
        expect(json_response).to be_an Array
        expect(json_response.map { |mr| mr['id'] })
          .not_to include(merge_request3.id)
      end

87 88 89 90 91
      it 'returns an array of merge requests created by current user if no scope is given' do
        merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch')

        get api('/merge_requests', user2)

L
Lin Jen-Shin 已提交
92
        expect(response).to have_gitlab_http_status(200)
93 94 95 96 97
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(merge_request3.id)
      end

98 99 100
      it 'returns an array of merge requests authored by the given user' do
        merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch')

101
        get api('/merge_requests', user), author_id: user2.id, scope: :all
102

L
Lin Jen-Shin 已提交
103
        expect(response).to have_gitlab_http_status(200)
104 105 106 107 108 109 110 111
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(merge_request3.id)
      end

      it 'returns an array of merge requests assigned to the given user' do
        merge_request3 = create(:merge_request, :simple, author: user, assignee: user2, source_project: project2, target_project: project2, source_branch: 'other-branch')

112
        get api('/merge_requests', user), assignee_id: user2.id, scope: :all
113

L
Lin Jen-Shin 已提交
114
        expect(response).to have_gitlab_http_status(200)
115 116 117 118 119 120 121 122 123 124
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(merge_request3.id)
      end

      it 'returns an array of merge requests assigned to me' do
        merge_request3 = create(:merge_request, :simple, author: user, assignee: user2, source_project: project2, target_project: project2, source_branch: 'other-branch')

        get api('/merge_requests', user2), scope: 'assigned-to-me'

L
Lin Jen-Shin 已提交
125
        expect(response).to have_gitlab_http_status(200)
126 127 128 129 130 131 132 133 134 135
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(merge_request3.id)
      end

      it 'returns an array of merge requests created by me' do
        merge_request3 = create(:merge_request, :simple, author: user2, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch')

        get api('/merge_requests', user2), scope: 'created-by-me'

L
Lin Jen-Shin 已提交
136
        expect(response).to have_gitlab_http_status(200)
137 138 139 140
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(merge_request3.id)
      end
141 142 143 144 145 146 147 148 149 150 151 152

      it 'returns merge requests reacted by the authenticated user by the given emoji' do
        merge_request3 = create(:merge_request, :simple, author: user, assignee: user, source_project: project2, target_project: project2, source_branch: 'other-branch')
        award_emoji = create(:award_emoji, awardable: merge_request3, user: user2, name: 'star')

        get api('/merge_requests', user2), my_reaction_emoji: award_emoji.name, scope: 'all'

        expect(response).to have_gitlab_http_status(200)
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(merge_request3.id)
      end
153 154 155
    end
  end

V
Valeriy Sizov 已提交
156 157
  describe "GET /projects/:id/merge_requests" do
    context "when unauthenticated" do
158 159 160
      it 'returns merge requests for public projects' do
        get api("/projects/#{project.id}/merge_requests")

161
        expect(response).to have_gitlab_http_status(200)
162 163 164 165 166
        expect(json_response).to be_an Array
      end

      it "returns 404 for non public projects" do
        project = create(:project, :private)
H
Hiroyuki Sato 已提交
167
        get api("/projects/#{project.id}/merge_requests")
168

169
        expect(response).to have_gitlab_http_status(404)
V
Valeriy Sizov 已提交
170 171 172 173
      end
    end

    context "when authenticated" do
S
Stan Hu 已提交
174 175 176 177 178 179 180 181 182 183 184 185
      it 'avoids N+1 queries' do
        control_count = ActiveRecord::QueryRecorder.new do
          get api("/projects/#{project.id}/merge_requests", user)
        end.count

        create(:merge_request, state: 'closed', milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time)

        expect do
          get api("/projects/#{project.id}/merge_requests", user)
        end.not_to exceed_query_limit(control_count)
      end

186
      it "returns an array of all merge_requests" do
H
Hiroyuki Sato 已提交
187
        get api("/projects/#{project.id}/merge_requests", user)
188

L
Lin Jen-Shin 已提交
189
        expect(response).to have_gitlab_http_status(200)
190
        expect(response).to include_pagination_headers
191 192 193
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(3)
        expect(json_response.last['title']).to eq(merge_request.title)
194
        expect(json_response.last).to have_key('web_url')
195 196 197
        expect(json_response.last['sha']).to eq(merge_request.diff_head_sha)
        expect(json_response.last['merge_commit_sha']).to be_nil
        expect(json_response.last['merge_commit_sha']).to eq(merge_request.merge_commit_sha)
198 199 200
        expect(json_response.last['downvotes']).to eq(1)
        expect(json_response.last['upvotes']).to eq(1)
        expect(json_response.last['labels']).to eq([label2.title, label.title])
201 202 203 204
        expect(json_response.first['title']).to eq(merge_request_merged.title)
        expect(json_response.first['sha']).to eq(merge_request_merged.diff_head_sha)
        expect(json_response.first['merge_commit_sha']).not_to be_nil
        expect(json_response.first['merge_commit_sha']).to eq(merge_request_merged.merge_commit_sha)
V
Valeriy Sizov 已提交
205
      end
206

S
Stan Hu 已提交
207
      it "returns an array of all merge_requests using simple mode" do
208
        get api("/projects/#{project.id}/merge_requests?view=simple", user)
S
Stan Hu 已提交
209

L
Lin Jen-Shin 已提交
210
        expect(response).to have_gitlab_http_status(200)
S
Stan Hu 已提交
211 212 213 214 215 216 217 218 219 220 221 222
        expect(response).to include_pagination_headers
        expect(json_response.last.keys).to match_array(%w(id iid title web_url created_at description project_id state updated_at))
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(3)
        expect(json_response.last['iid']).to eq(merge_request.iid)
        expect(json_response.last['title']).to eq(merge_request.title)
        expect(json_response.last).to have_key('web_url')
        expect(json_response.first['iid']).to eq(merge_request_merged.iid)
        expect(json_response.first['title']).to eq(merge_request_merged.title)
        expect(json_response.first).to have_key('web_url')
      end

223
      it "returns an array of all merge_requests" do
224
        get api("/projects/#{project.id}/merge_requests?state", user)
225

L
Lin Jen-Shin 已提交
226
        expect(response).to have_gitlab_http_status(200)
227
        expect(response).to include_pagination_headers
228 229 230
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(3)
        expect(json_response.last['title']).to eq(merge_request.title)
231
      end
232

233
      it "returns an array of open merge_requests" do
234
        get api("/projects/#{project.id}/merge_requests?state=opened", user)
235

L
Lin Jen-Shin 已提交
236
        expect(response).to have_gitlab_http_status(200)
237
        expect(response).to include_pagination_headers
238 239 240
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.last['title']).to eq(merge_request.title)
241
      end
242

243
      it "returns an array of closed merge_requests" do
244
        get api("/projects/#{project.id}/merge_requests?state=closed", user)
245

L
Lin Jen-Shin 已提交
246
        expect(response).to have_gitlab_http_status(200)
247
        expect(response).to include_pagination_headers
248
        expect(json_response).to be_an Array
249 250
        expect(json_response.length).to eq(1)
        expect(json_response.first['title']).to eq(merge_request_closed.title)
251
      end
252

253
      it "returns an array of merged merge_requests" do
254
        get api("/projects/#{project.id}/merge_requests?state=merged", user)
255

L
Lin Jen-Shin 已提交
256
        expect(response).to have_gitlab_http_status(200)
257
        expect(response).to include_pagination_headers
258 259 260
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['title']).to eq(merge_request_merged.title)
261
      end
262

263 264 265
      it 'returns merge_request by "iids" array' do
        get api("/projects/#{project.id}/merge_requests", user), iids: [merge_request.iid, merge_request_closed.iid]

L
Lin Jen-Shin 已提交
266
        expect(response).to have_gitlab_http_status(200)
267 268 269 270 271 272
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(2)
        expect(json_response.first['title']).to eq merge_request_closed.title
        expect(json_response.first['id']).to eq merge_request_closed.id
      end

273 274 275
      it 'matches V4 response schema' do
        get api("/projects/#{project.id}/merge_requests", user)

L
Lin Jen-Shin 已提交
276
        expect(response).to have_gitlab_http_status(200)
277 278 279
        expect(response).to match_response_schema('public_api/v4/merge_requests')
      end

280 281 282
      it 'returns an empty array if no issue matches milestone' do
        get api("/projects/#{project.id}/merge_requests", user), milestone: '1.0.0'

L
Lin Jen-Shin 已提交
283
        expect(response).to have_gitlab_http_status(200)
284 285 286 287 288 289 290
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(0)
      end

      it 'returns an empty array if milestone does not exist' do
        get api("/projects/#{project.id}/merge_requests", user), milestone: 'foo'

L
Lin Jen-Shin 已提交
291
        expect(response).to have_gitlab_http_status(200)
292 293 294 295 296 297 298 299 300 301 302 303 304 305
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(0)
      end

      it 'returns an array of merge requests in given milestone' do
        get api("/projects/#{project.id}/merge_requests", user), milestone: '0.9'

        expect(json_response.first['title']).to eq merge_request_closed.title
        expect(json_response.first['id']).to eq merge_request_closed.id
      end

      it 'returns an array of merge requests matching state in milestone' do
        get api("/projects/#{project.id}/merge_requests", user), milestone: '0.9', state: 'closed'

L
Lin Jen-Shin 已提交
306
        expect(response).to have_gitlab_http_status(200)
307 308 309 310 311 312 313 314
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(merge_request_closed.id)
      end

      it 'returns an array of labeled merge requests' do
        get api("/projects/#{project.id}/merge_requests?labels=#{label.title}", user)

L
Lin Jen-Shin 已提交
315
        expect(response).to have_gitlab_http_status(200)
316 317
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
318
        expect(json_response.first['labels']).to eq([label2.title, label.title])
319 320 321 322 323
      end

      it 'returns an array of labeled merge requests where all labels match' do
        get api("/projects/#{project.id}/merge_requests?labels=#{label.title},foo,bar", user)

L
Lin Jen-Shin 已提交
324
        expect(response).to have_gitlab_http_status(200)
325 326 327 328 329 330 331
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(0)
      end

      it 'returns an empty array if no merge request matches labels' do
        get api("/projects/#{project.id}/merge_requests?labels=foo,bar", user)

L
Lin Jen-Shin 已提交
332
        expect(response).to have_gitlab_http_status(200)
333 334 335 336
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(0)
      end

337 338 339 340 341 342 343 344 345 346 347 348 349 350
      it 'returns an array of labeled merge requests that are merged for a milestone' do
        bug_label = create(:label, title: 'bug', color: '#FFAABB', project: project)

        mr1 = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone)
        mr2 = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone1)
        mr3 = create(:merge_request, state: "closed", source_project: project, target_project: project, milestone: milestone1)
        _mr = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone1)

        create(:label_link, label: bug_label, target: mr1)
        create(:label_link, label: bug_label, target: mr2)
        create(:label_link, label: bug_label, target: mr3)

        get api("/projects/#{project.id}/merge_requests?labels=#{bug_label.title}&milestone=#{milestone1.title}&state=merged", user)

L
Lin Jen-Shin 已提交
351
        expect(response).to have_gitlab_http_status(200)
352 353 354 355 356
        expect(json_response).to be_an Array
        expect(json_response.length).to eq(1)
        expect(json_response.first['id']).to eq(mr2.id)
      end

357 358 359 360 361 362
      context "with ordering" do
        before do
          @mr_later = mr_with_later_created_and_updated_at_time
          @mr_earlier = mr_with_earlier_created_and_updated_at_time
        end

363
        it "returns an array of merge_requests in ascending order" do
364
          get api("/projects/#{project.id}/merge_requests?sort=asc", user)
365

L
Lin Jen-Shin 已提交
366
          expect(response).to have_gitlab_http_status(200)
367
          expect(response).to include_pagination_headers
368 369
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(3)
370
          response_dates = json_response.map { |merge_request| merge_request['created_at'] }
S
Stan Hu 已提交
371
          expect(response_dates).to eq(response_dates.sort)
372
        end
D
Dmitriy Zaporozhets 已提交
373

374
        it "returns an array of merge_requests in descending order" do
375
          get api("/projects/#{project.id}/merge_requests?sort=desc", user)
376

L
Lin Jen-Shin 已提交
377
          expect(response).to have_gitlab_http_status(200)
378
          expect(response).to include_pagination_headers
379 380
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(3)
381
          response_dates = json_response.map { |merge_request| merge_request['created_at'] }
S
Stan Hu 已提交
382
          expect(response_dates).to eq(response_dates.sort.reverse)
383
        end
D
Dmitriy Zaporozhets 已提交
384

385
        it "returns an array of merge_requests ordered by updated_at" do
386
          get api("/projects/#{project.id}/merge_requests?order_by=updated_at", user)
387

L
Lin Jen-Shin 已提交
388
          expect(response).to have_gitlab_http_status(200)
389
          expect(response).to include_pagination_headers
390 391
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(3)
392
          response_dates = json_response.map { |merge_request| merge_request['updated_at'] }
S
Stan Hu 已提交
393
          expect(response_dates).to eq(response_dates.sort.reverse)
394
        end
D
Dmitriy Zaporozhets 已提交
395

396
        it "returns an array of merge_requests ordered by created_at" do
S
Stan Hu 已提交
397
          get api("/projects/#{project.id}/merge_requests?order_by=created_at&sort=asc", user)
398

L
Lin Jen-Shin 已提交
399
          expect(response).to have_gitlab_http_status(200)
400
          expect(response).to include_pagination_headers
401 402
          expect(json_response).to be_an Array
          expect(json_response.length).to eq(3)
403
          response_dates = json_response.map { |merge_request| merge_request['created_at'] }
S
Stan Hu 已提交
404
          expect(response_dates).to eq(response_dates.sort)
405
        end
406
      end
V
Valeriy Sizov 已提交
407 408 409
    end
  end

410
  describe "GET /projects/:id/merge_requests/:merge_request_iid" do
411
    it 'exposes known attributes' do
412
      get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user)
413

L
Lin Jen-Shin 已提交
414
      expect(response).to have_gitlab_http_status(200)
415 416 417 418 419 420 421 422 423
      expect(json_response['id']).to eq(merge_request.id)
      expect(json_response['iid']).to eq(merge_request.iid)
      expect(json_response['project_id']).to eq(merge_request.project.id)
      expect(json_response['title']).to eq(merge_request.title)
      expect(json_response['description']).to eq(merge_request.description)
      expect(json_response['state']).to eq(merge_request.state)
      expect(json_response['created_at']).to be_present
      expect(json_response['updated_at']).to be_present
      expect(json_response['labels']).to eq(merge_request.label_names)
424
      expect(json_response['milestone']).to be_a Hash
425 426 427 428
      expect(json_response['assignee']).to be_a Hash
      expect(json_response['author']).to be_a Hash
      expect(json_response['target_branch']).to eq(merge_request.target_branch)
      expect(json_response['source_branch']).to eq(merge_request.source_branch)
429 430
      expect(json_response['upvotes']).to eq(1)
      expect(json_response['downvotes']).to eq(1)
431 432 433
      expect(json_response['source_project_id']).to eq(merge_request.source_project.id)
      expect(json_response['target_project_id']).to eq(merge_request.target_project.id)
      expect(json_response['work_in_progress']).to be_falsy
J
James Lopez 已提交
434
      expect(json_response['merge_when_pipeline_succeeds']).to be_falsy
435
      expect(json_response['merge_status']).to eq('can_be_merged')
436 437
      expect(json_response['should_close_merge_request']).to be_falsy
      expect(json_response['force_close_merge_request']).to be_falsy
438 439
    end

440
    it "returns merge_request" do
441
      get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user)
L
Lin Jen-Shin 已提交
442
      expect(response).to have_gitlab_http_status(200)
443 444
      expect(json_response['title']).to eq(merge_request.title)
      expect(json_response['iid']).to eq(merge_request.iid)
445
      expect(json_response['work_in_progress']).to eq(false)
446
      expect(json_response['merge_status']).to eq('can_be_merged')
447 448
      expect(json_response['should_close_merge_request']).to be_falsy
      expect(json_response['force_close_merge_request']).to be_falsy
V
Valeriy Sizov 已提交
449
    end
450

451
    it "returns a 404 error if merge_request_iid not found" do
452
      get api("/projects/#{project.id}/merge_requests/999", user)
L
Lin Jen-Shin 已提交
453
      expect(response).to have_gitlab_http_status(404)
454
    end
455

456 457 458
    it "returns a 404 error if merge_request `id` is used instead of iid" do
      get api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user)

L
Lin Jen-Shin 已提交
459
      expect(response).to have_gitlab_http_status(404)
460 461
    end

462 463 464
    context 'Work in Progress' do
      let!(:merge_request_wip) { create(:merge_request, author: user, assignee: user, source_project: project, target_project: project, title: "WIP: Test", created_at: base_time + 1.second) }

465
      it "returns merge_request" do
466
        get api("/projects/#{project.id}/merge_requests/#{merge_request_wip.iid}", user)
L
Lin Jen-Shin 已提交
467
        expect(response).to have_gitlab_http_status(200)
468 469 470
        expect(json_response['work_in_progress']).to eq(true)
      end
    end
V
Valeriy Sizov 已提交
471 472
  end

473
  describe 'GET /projects/:id/merge_requests/:merge_request_iid/commits' do
V
Valery Sizov 已提交
474
    it 'returns a 200 when merge request is valid' do
475
      get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/commits", user)
V
Valery Sizov 已提交
476 477
      commit = merge_request.commits.first

L
Lin Jen-Shin 已提交
478
      expect(response).to have_gitlab_http_status(200)
479 480
      expect(response).to include_pagination_headers
      expect(json_response).to be_an Array
V
Valery Sizov 已提交
481 482 483
      expect(json_response.size).to eq(merge_request.commits.size)
      expect(json_response.first['id']).to eq(commit.id)
      expect(json_response.first['title']).to eq(commit.title)
484 485
    end

486
    it 'returns a 404 when merge_request_iid not found' do
487
      get api("/projects/#{project.id}/merge_requests/999/commits", user)
L
Lin Jen-Shin 已提交
488
      expect(response).to have_gitlab_http_status(404)
489
    end
490 491 492 493

    it 'returns a 404 when merge_request id is used instead of iid' do
      get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/commits", user)

L
Lin Jen-Shin 已提交
494
      expect(response).to have_gitlab_http_status(404)
495
    end
496 497
  end

498
  describe 'GET /projects/:id/merge_requests/:merge_request_iid/changes' do
499
    it 'returns the change information of the merge_request' do
500
      get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
501

L
Lin Jen-Shin 已提交
502
      expect(response).to have_gitlab_http_status(200)
503 504 505
      expect(json_response['changes'].size).to eq(merge_request.diffs.size)
    end

506
    it 'returns a 404 when merge_request_iid not found' do
507
      get api("/projects/#{project.id}/merge_requests/999/changes", user)
L
Lin Jen-Shin 已提交
508
      expect(response).to have_gitlab_http_status(404)
509
    end
510 511 512 513

    it 'returns a 404 when merge_request id is used instead of iid' do
      get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/changes", user)

L
Lin Jen-Shin 已提交
514
      expect(response).to have_gitlab_http_status(404)
515
    end
516 517
  end

V
Valeriy Sizov 已提交
518
  describe "POST /projects/:id/merge_requests" do
I
Izaak Alpert 已提交
519
    context 'between branches projects' do
520
      it "returns merge_request" do
H
Hiroyuki Sato 已提交
521
        post api("/projects/#{project.id}/merge_requests", user),
522
             title: 'Test merge_request',
523
             source_branch: 'feature_conflict',
524 525
             target_branch: 'master',
             author: user,
526
             labels: 'label, label2',
527
             milestone_id: milestone.id
528

L
Lin Jen-Shin 已提交
529
        expect(response).to have_gitlab_http_status(201)
530
        expect(json_response['title']).to eq('Test merge_request')
D
Douwe Maan 已提交
531
        expect(json_response['labels']).to eq(%w(label label2))
532
        expect(json_response['milestone']['id']).to eq(milestone.id)
533
        expect(json_response['force_remove_source_branch']).to be_falsy
I
Izaak Alpert 已提交
534
      end
535

536
      it "returns 422 when source_branch equals target_branch" do
H
Hiroyuki Sato 已提交
537
        post api("/projects/#{project.id}/merge_requests", user),
538
        title: "Test merge_request", source_branch: "master", target_branch: "master", author: user
L
Lin Jen-Shin 已提交
539
        expect(response).to have_gitlab_http_status(422)
I
Izaak Alpert 已提交
540
      end
541

542
      it "returns 400 when source_branch is missing" do
H
Hiroyuki Sato 已提交
543
        post api("/projects/#{project.id}/merge_requests", user),
544
        title: "Test merge_request", target_branch: "master", author: user
L
Lin Jen-Shin 已提交
545
        expect(response).to have_gitlab_http_status(400)
I
Izaak Alpert 已提交
546
      end
547

548
      it "returns 400 when target_branch is missing" do
H
Hiroyuki Sato 已提交
549
        post api("/projects/#{project.id}/merge_requests", user),
550
        title: "Test merge_request", source_branch: "markdown", author: user
L
Lin Jen-Shin 已提交
551
        expect(response).to have_gitlab_http_status(400)
I
Izaak Alpert 已提交
552 553
      end

554
      it "returns 400 when title is missing" do
H
Hiroyuki Sato 已提交
555
        post api("/projects/#{project.id}/merge_requests", user),
556
        target_branch: 'master', source_branch: 'markdown'
L
Lin Jen-Shin 已提交
557
        expect(response).to have_gitlab_http_status(400)
I
Izaak Alpert 已提交
558
      end
559

560
      it 'allows special label names' do
561 562
        post api("/projects/#{project.id}/merge_requests", user),
             title: 'Test merge_request',
563
             source_branch: 'markdown',
564 565
             target_branch: 'master',
             author: user,
566
             labels: 'label, label?, label&foo, ?, &'
L
Lin Jen-Shin 已提交
567
        expect(response).to have_gitlab_http_status(201)
568 569 570 571 572
        expect(json_response['labels']).to include 'label'
        expect(json_response['labels']).to include 'label?'
        expect(json_response['labels']).to include 'label&foo'
        expect(json_response['labels']).to include '?'
        expect(json_response['labels']).to include '&'
573
      end
J
jubianchi 已提交
574 575 576 577 578

      context 'with existing MR' do
        before do
          post api("/projects/#{project.id}/merge_requests", user),
               title: 'Test merge_request',
579
               source_branch: 'feature_conflict',
J
jubianchi 已提交
580 581 582 583 584
               target_branch: 'master',
               author: user
          @mr = MergeRequest.all.last
        end

585
        it 'returns 409 when MR already exists for source/target' do
J
jubianchi 已提交
586 587 588
          expect do
            post api("/projects/#{project.id}/merge_requests", user),
                 title: 'New test merge_request',
589
                 source_branch: 'feature_conflict',
J
jubianchi 已提交
590 591 592
                 target_branch: 'master',
                 author: user
          end.to change { MergeRequest.count }.by(0)
L
Lin Jen-Shin 已提交
593
          expect(response).to have_gitlab_http_status(409)
J
jubianchi 已提交
594 595
        end
      end
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616

      context 'accepts remove_source_branch parameter' do
        let(:params) do
          { title: 'Test merge_request',
            source_branch: 'markdown',
            target_branch: 'master',
            author: user }
        end

        it 'sets force_remove_source_branch to false' do
          post api("/projects/#{project.id}/merge_requests", user), params.merge(remove_source_branch: false)

          expect(json_response['force_remove_source_branch']).to be_falsy
        end

        it 'sets force_remove_source_branch to true' do
          post api("/projects/#{project.id}/merge_requests", user), params.merge(remove_source_branch: true)

          expect(json_response['force_remove_source_branch']).to be_truthy
        end
      end
617
    end
618

I
Izaak Alpert 已提交
619
    context 'forked projects' do
D
Dmitriy Zaporozhets 已提交
620
      let!(:user2) { create(:user) }
B
Bob Van Landuyt 已提交
621
      let!(:forked_project) { fork_project(project, user2) }
622
      let!(:unrelated_project) { create(:project,  namespace: create(:user).namespace, creator_id: user2.id) }
I
Izaak Alpert 已提交
623

624
      before do
B
Bob Van Landuyt 已提交
625
        forked_project.add_reporter(user2)
626

627
        allow_any_instance_of(MergeRequest).to receive(:write_ref)
I
Izaak Alpert 已提交
628 629
      end

630
      it "returns merge_request" do
B
Bob Van Landuyt 已提交
631
        post api("/projects/#{forked_project.id}/merge_requests", user2),
632 633
          title: 'Test merge_request', source_branch: "feature_conflict", target_branch: "master",
          author: user2, target_project_id: project.id, description: 'Test description for Test merge_request'
634
        expect(response).to have_gitlab_http_status(201)
635 636
        expect(json_response['title']).to eq('Test merge_request')
        expect(json_response['description']).to eq('Test description for Test merge_request')
I
Izaak Alpert 已提交
637 638
      end

639
      it "does not return 422 when source_branch equals target_branch" do
B
Bob Van Landuyt 已提交
640 641 642 643
        expect(project.id).not_to eq(forked_project.id)
        expect(forked_project.forked?).to be_truthy
        expect(forked_project.forked_from_project).to eq(project)
        post api("/projects/#{forked_project.id}/merge_requests", user2),
644
        title: 'Test merge_request', source_branch: "master", target_branch: "master", author: user2, target_project_id: project.id
645
        expect(response).to have_gitlab_http_status(201)
646
        expect(json_response['title']).to eq('Test merge_request')
I
Izaak Alpert 已提交
647 648
      end

649 650 651
      it 'returns 422 when target project has disabled merge requests' do
        project.project_feature.update(merge_requests_access_level: 0)

B
Bob Van Landuyt 已提交
652
        post api("/projects/#{forked_project.id}/merge_requests", user2),
653 654 655 656 657 658
             title: 'Test',
             target_branch: 'master',
             source_branch: 'markdown',
             author: user2,
             target_project_id: project.id

L
Lin Jen-Shin 已提交
659
        expect(response).to have_gitlab_http_status(422)
660 661
      end

662
      it "returns 400 when source_branch is missing" do
B
Bob Van Landuyt 已提交
663
        post api("/projects/#{forked_project.id}/merge_requests", user2),
664
        title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
L
Lin Jen-Shin 已提交
665
        expect(response).to have_gitlab_http_status(400)
I
Izaak Alpert 已提交
666 667
      end

668
      it "returns 400 when target_branch is missing" do
B
Bob Van Landuyt 已提交
669
        post api("/projects/#{forked_project.id}/merge_requests", user2),
670
        title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id
L
Lin Jen-Shin 已提交
671
        expect(response).to have_gitlab_http_status(400)
I
Izaak Alpert 已提交
672 673
      end

674
      it "returns 400 when title is missing" do
B
Bob Van Landuyt 已提交
675
        post api("/projects/#{forked_project.id}/merge_requests", user2),
676
        target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: project.id
L
Lin Jen-Shin 已提交
677
        expect(response).to have_gitlab_http_status(400)
I
Izaak Alpert 已提交
678 679
      end

J
jubianchi 已提交
680
      context 'when target_branch is specified' do
681
        it 'returns 422 if targeting a different fork' do
B
Bob Van Landuyt 已提交
682
          post api("/projects/#{forked_project.id}/merge_requests", user2),
J
jubianchi 已提交
683 684
               title: 'Test merge_request',
               target_branch: 'master',
685
               source_branch: 'markdown',
J
jubianchi 已提交
686 687
               author: user2,
               target_project_id: unrelated_project.id
L
Lin Jen-Shin 已提交
688
          expect(response).to have_gitlab_http_status(422)
J
jubianchi 已提交
689
        end
I
Izaak Alpert 已提交
690 691
      end

692
      it "returns 201 when target_branch is specified and for the same project" do
B
Bob Van Landuyt 已提交
693 694
        post api("/projects/#{forked_project.id}/merge_requests", user2),
        title: 'Test merge_request', target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: forked_project.id
L
Lin Jen-Shin 已提交
695
        expect(response).to have_gitlab_http_status(201)
I
Izaak Alpert 已提交
696
      end
697
    end
V
Valeriy Sizov 已提交
698 699
  end

700
  describe "DELETE /projects/:id/merge_requests/:merge_request_iid" do
701 702
    context "when the user is developer" do
      let(:developer) { create(:user) }
Z
Zeger-Jan van de Weg 已提交
703

704 705 706
      before do
        project.team << [developer, :developer]
      end
Z
Zeger-Jan van de Weg 已提交
707

708
      it "denies the deletion of the merge request" do
709
        delete api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", developer)
L
Lin Jen-Shin 已提交
710
        expect(response).to have_gitlab_http_status(403)
711
      end
Z
Zeger-Jan van de Weg 已提交
712
    end
713

714 715
    context "when the user is project owner" do
      it "destroys the merge request owners can destroy" do
716
        delete api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user)
717

L
Lin Jen-Shin 已提交
718
        expect(response).to have_gitlab_http_status(204)
719
      end
720 721 722 723

      it "returns 404 for an invalid merge request IID" do
        delete api("/projects/#{project.id}/merge_requests/12345", user)

L
Lin Jen-Shin 已提交
724
        expect(response).to have_gitlab_http_status(404)
725 726 727 728 729
      end

      it "returns 404 if the merge request id is used instead of iid" do
        delete api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user)

L
Lin Jen-Shin 已提交
730
        expect(response).to have_gitlab_http_status(404)
731
      end
732 733 734 735

      it_behaves_like '412 response' do
        let(:request) { api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user) }
      end
736
    end
Z
Zeger-Jan van de Weg 已提交
737 738
  end

739
  describe "PUT /projects/:id/merge_requests/:merge_request_iid/merge" do
740
    let(:pipeline) { create(:ci_pipeline_without_jobs) }
741

742
    it "returns merge_request in case of success" do
743
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
744

L
Lin Jen-Shin 已提交
745
      expect(response).to have_gitlab_http_status(200)
746 747
    end

748
    it "returns 406 if branch can't be merged" do
749 750
      allow_any_instance_of(MergeRequest)
        .to receive(:can_be_merged?).and_return(false)
751

752
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
753

L
Lin Jen-Shin 已提交
754
      expect(response).to have_gitlab_http_status(406)
755
      expect(json_response['message']).to eq('Branch cannot be merged')
A
Andrew8xx8 已提交
756
    end
D
Dmitriy Zaporozhets 已提交
757

758
    it "returns 405 if merge_request is not open" do
D
Dmitriy Zaporozhets 已提交
759
      merge_request.close
760
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
L
Lin Jen-Shin 已提交
761
      expect(response).to have_gitlab_http_status(405)
762
      expect(json_response['message']).to eq('405 Method Not Allowed')
D
Dmitriy Zaporozhets 已提交
763 764
    end

765
    it "returns 405 if merge_request is a work in progress" do
766
      merge_request.update_attribute(:title, "WIP: #{merge_request.title}")
767
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
L
Lin Jen-Shin 已提交
768
      expect(response).to have_gitlab_http_status(405)
769 770 771
      expect(json_response['message']).to eq('405 Method Not Allowed')
    end

772
    it 'returns 405 if the build failed for a merge request that requires success' do
773
      allow_any_instance_of(MergeRequest).to receive(:mergeable_ci_state?).and_return(false)
774

775
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
776

L
Lin Jen-Shin 已提交
777
      expect(response).to have_gitlab_http_status(405)
778 779 780
      expect(json_response['message']).to eq('405 Method Not Allowed')
    end

781
    it "returns 401 if user has no permissions to merge" do
D
Dmitriy Zaporozhets 已提交
782 783
      user2 = create(:user)
      project.team << [user2, :reporter]
784
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user2)
L
Lin Jen-Shin 已提交
785
      expect(response).to have_gitlab_http_status(401)
786
      expect(json_response['message']).to eq('401 Unauthorized')
D
Dmitriy Zaporozhets 已提交
787
    end
788

789
    it "returns 409 if the SHA parameter doesn't match" do
790
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), sha: merge_request.diff_head_sha.reverse
791

L
Lin Jen-Shin 已提交
792
      expect(response).to have_gitlab_http_status(409)
793 794 795 796
      expect(json_response['message']).to start_with('SHA does not match HEAD of source branch')
    end

    it "succeeds if the SHA parameter matches" do
797
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), sha: merge_request.diff_head_sha
798

L
Lin Jen-Shin 已提交
799
      expect(response).to have_gitlab_http_status(200)
800 801
    end

802
    it "enables merge when pipeline succeeds if the pipeline is active" do
803
      allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline)
804
      allow(pipeline).to receive(:active?).and_return(true)
805

806
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), merge_when_pipeline_succeeds: true
807

L
Lin Jen-Shin 已提交
808
      expect(response).to have_gitlab_http_status(200)
809
      expect(json_response['title']).to eq('Test')
J
James Lopez 已提交
810
      expect(json_response['merge_when_pipeline_succeeds']).to eq(true)
811
    end
812

813 814 815 816 817 818 819
    it "enables merge when pipeline succeeds if the pipeline is active and only_allow_merge_if_pipeline_succeeds is true" do
      allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline)
      allow(pipeline).to receive(:active?).and_return(true)
      project.update_attribute(:only_allow_merge_if_pipeline_succeeds, true)

      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), merge_when_pipeline_succeeds: true

L
Lin Jen-Shin 已提交
820
      expect(response).to have_gitlab_http_status(200)
821 822 823 824
      expect(json_response['title']).to eq('Test')
      expect(json_response['merge_when_pipeline_succeeds']).to eq(true)
    end

825 826 827
    it "returns 404 for an invalid merge request IID" do
      put api("/projects/#{project.id}/merge_requests/12345/merge", user)

L
Lin Jen-Shin 已提交
828
      expect(response).to have_gitlab_http_status(404)
829 830 831 832 833
    end

    it "returns 404 if the merge request id is used instead of iid" do
      put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)

L
Lin Jen-Shin 已提交
834
      expect(response).to have_gitlab_http_status(404)
835
    end
A
Andrew8xx8 已提交
836 837
  end

838
  describe "PUT /projects/:id/merge_requests/:merge_request_iid" do
839 840
    context "to close a MR" do
      it "returns merge_request" do
841
        put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), state_event: "close"
842

L
Lin Jen-Shin 已提交
843
        expect(response).to have_gitlab_http_status(200)
844 845 846 847
        expect(json_response['state']).to eq('closed')
      end
    end

848
    it "updates title and returns merge_request" do
849
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), title: "New title"
L
Lin Jen-Shin 已提交
850
      expect(response).to have_gitlab_http_status(200)
851
      expect(json_response['title']).to eq('New title')
V
Valeriy Sizov 已提交
852
    end
853

854
    it "updates description and returns merge_request" do
855
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), description: "New description"
L
Lin Jen-Shin 已提交
856
      expect(response).to have_gitlab_http_status(200)
857
      expect(json_response['description']).to eq('New description')
858 859
    end

860
    it "updates milestone_id and returns merge_request" do
861
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), milestone_id: milestone.id
L
Lin Jen-Shin 已提交
862
      expect(response).to have_gitlab_http_status(200)
863 864 865
      expect(json_response['milestone']['id']).to eq(milestone.id)
    end

866
    it "returns merge_request with renamed target_branch" do
867
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), target_branch: "wiki"
L
Lin Jen-Shin 已提交
868
      expect(response).to have_gitlab_http_status(200)
869
      expect(json_response['target_branch']).to eq('wiki')
870
    end
871

872
    it "returns merge_request that removes the source branch" do
873
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), remove_source_branch: true
874

L
Lin Jen-Shin 已提交
875
      expect(response).to have_gitlab_http_status(200)
876 877 878
      expect(json_response['force_remove_source_branch']).to be_truthy
    end

879
    it 'allows special label names' do
880
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user),
881 882 883
        title: 'new issue',
        labels: 'label, label?, label&foo, ?, &'

884 885 886 887 888 889
      expect(response.status).to eq(200)
      expect(json_response['labels']).to include 'label'
      expect(json_response['labels']).to include 'label?'
      expect(json_response['labels']).to include 'label&foo'
      expect(json_response['labels']).to include '?'
      expect(json_response['labels']).to include '&'
890
    end
891 892

    it 'does not update state when title is empty' do
893
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), state_event: 'close', title: nil
894 895

      merge_request.reload
L
Lin Jen-Shin 已提交
896
      expect(response).to have_gitlab_http_status(400)
897 898 899 900
      expect(merge_request.state).to eq('opened')
    end

    it 'does not update state when target_branch is empty' do
901
      put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), state_event: 'close', target_branch: nil
902 903

      merge_request.reload
L
Lin Jen-Shin 已提交
904
      expect(response).to have_gitlab_http_status(400)
905 906
      expect(merge_request.state).to eq('opened')
    end
907 908 909 910

    it "returns 404 for an invalid merge request IID" do
      put api("/projects/#{project.id}/merge_requests/12345", user), state_event: "close"

L
Lin Jen-Shin 已提交
911
      expect(response).to have_gitlab_http_status(404)
912 913 914 915 916
    end

    it "returns 404 if the merge request id is used instead of iid" do
      put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: "close"

L
Lin Jen-Shin 已提交
917
      expect(response).to have_gitlab_http_status(404)
918
    end
V
Valeriy Sizov 已提交
919 920
  end

921
  describe 'GET :id/merge_requests/:merge_request_iid/closes_issues' do
922 923 924 925 926
    it 'returns the issue that will be closed on merge' do
      issue = create(:issue, project: project)
      mr = merge_request.tap do |mr|
        mr.update_attribute(:description, "Closes #{issue.to_reference(mr.project)}")
      end
927

928
      get api("/projects/#{project.id}/merge_requests/#{mr.iid}/closes_issues", user)
929

L
Lin Jen-Shin 已提交
930
      expect(response).to have_gitlab_http_status(200)
931
      expect(response).to include_pagination_headers
932 933 934 935 936
      expect(json_response).to be_an Array
      expect(json_response.length).to eq(1)
      expect(json_response.first['id']).to eq(issue.id)
    end

937
    it 'returns an empty array when there are no issues to be closed' do
938
      get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/closes_issues", user)
939

L
Lin Jen-Shin 已提交
940
      expect(response).to have_gitlab_http_status(200)
941
      expect(response).to include_pagination_headers
942 943 944
      expect(json_response).to be_an Array
      expect(json_response.length).to eq(0)
    end
945 946

    it 'handles external issues' do
947
      jira_project = create(:jira_project, :public, :repository, name: 'JIR_EXT1')
948 949 950 951 952
      ext_issue = ExternalIssue.new("#{jira_project.name}-123", jira_project)
      issue = create(:issue, project: jira_project)
      description = "Closes #{ext_issue.to_reference(jira_project)}\ncloses #{issue.to_reference}"
      merge_request = create(:merge_request,
        :simple, author: user, assignee: user, source_project: jira_project, description: description)
953

954
      get api("/projects/#{jira_project.id}/merge_requests/#{merge_request.iid}/closes_issues", user)
955

L
Lin Jen-Shin 已提交
956
      expect(response).to have_gitlab_http_status(200)
957
      expect(response).to include_pagination_headers
958
      expect(json_response).to be_an Array
959 960 961 962
      expect(json_response.length).to eq(2)
      expect(json_response.second['title']).to eq(ext_issue.title)
      expect(json_response.second['id']).to eq(ext_issue.id)
      expect(json_response.second['confidential']).to be_nil
963 964
      expect(json_response.first['title']).to eq(issue.title)
      expect(json_response.first['id']).to eq(issue.id)
965
      expect(json_response.first['confidential']).not_to be_nil
966
    end
967 968

    it 'returns 403 if the user has no access to the merge request' do
969
      project = create(:project, :private)
970 971 972 973
      merge_request = create(:merge_request, :simple, source_project: project)
      guest = create(:user)
      project.team << [guest, :guest]

974
      get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/closes_issues", guest)
975

L
Lin Jen-Shin 已提交
976
      expect(response).to have_gitlab_http_status(403)
977
    end
978 979 980 981

    it "returns 404 for an invalid merge request IID" do
      get api("/projects/#{project.id}/merge_requests/12345/closes_issues", user)

L
Lin Jen-Shin 已提交
982
      expect(response).to have_gitlab_http_status(404)
983 984 985 986 987
    end

    it "returns 404 if the merge request id is used instead of iid" do
      get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/closes_issues", user)

L
Lin Jen-Shin 已提交
988
      expect(response).to have_gitlab_http_status(404)
989
    end
990 991
  end

992
  describe 'POST :id/merge_requests/:merge_request_iid/subscribe' do
993
    it 'subscribes to a merge request' do
994
      post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/subscribe", admin)
995

L
Lin Jen-Shin 已提交
996
      expect(response).to have_gitlab_http_status(201)
997 998 999 1000
      expect(json_response['subscribed']).to eq(true)
    end

    it 'returns 304 if already subscribed' do
1001
      post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/subscribe", user)
1002

L
Lin Jen-Shin 已提交
1003
      expect(response).to have_gitlab_http_status(304)
1004
    end
1005 1006

    it 'returns 404 if the merge request is not found' do
1007
      post api("/projects/#{project.id}/merge_requests/123/subscribe", user)
1008

L
Lin Jen-Shin 已提交
1009
      expect(response).to have_gitlab_http_status(404)
1010
    end
1011

1012 1013 1014
    it 'returns 404 if the merge request id is used instead of iid' do
      post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/subscribe", user)

L
Lin Jen-Shin 已提交
1015
      expect(response).to have_gitlab_http_status(404)
1016 1017
    end

1018 1019 1020 1021
    it 'returns 403 if user has no access to read code' do
      guest = create(:user)
      project.team << [guest, :guest]

1022
      post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/subscribe", guest)
1023

L
Lin Jen-Shin 已提交
1024
      expect(response).to have_gitlab_http_status(403)
1025
    end
1026 1027
  end

1028
  describe 'POST :id/merge_requests/:merge_request_iid/unsubscribe' do
1029
    it 'unsubscribes from a merge request' do
1030
      post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/unsubscribe", user)
1031

L
Lin Jen-Shin 已提交
1032
      expect(response).to have_gitlab_http_status(201)
1033 1034 1035 1036
      expect(json_response['subscribed']).to eq(false)
    end

    it 'returns 304 if not subscribed' do
1037
      post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/unsubscribe", admin)
1038

L
Lin Jen-Shin 已提交
1039
      expect(response).to have_gitlab_http_status(304)
1040
    end
1041 1042

    it 'returns 404 if the merge request is not found' do
1043
      post api("/projects/#{project.id}/merge_requests/123/unsubscribe", user)
1044

L
Lin Jen-Shin 已提交
1045
      expect(response).to have_gitlab_http_status(404)
1046
    end
1047

1048 1049 1050
    it 'returns 404 if the merge request id is used instead of iid' do
      post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/unsubscribe", user)

L
Lin Jen-Shin 已提交
1051
      expect(response).to have_gitlab_http_status(404)
1052 1053
    end

1054 1055 1056 1057
    it 'returns 403 if user has no access to read code' do
      guest = create(:user)
      project.team << [guest, :guest]

1058
      post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/unsubscribe", guest)
1059

L
Lin Jen-Shin 已提交
1060
      expect(response).to have_gitlab_http_status(403)
1061
    end
1062 1063
  end

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
  describe 'POST :id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds' do
    before do
      ::MergeRequests::MergeWhenPipelineSucceedsService.new(merge_request.target_project, user).execute(merge_request)
    end

    it 'removes the merge_when_pipeline_succeeds status' do
      post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/cancel_merge_when_pipeline_succeeds", user)

      expect(response).to have_gitlab_http_status(201)
    end

    it 'returns 404 if the merge request is not found' do
      post api("/projects/#{project.id}/merge_requests/123/merge_when_pipeline_succeeds", user)

      expect(response).to have_gitlab_http_status(404)
    end

    it 'returns 404 if the merge request id is used instead of iid' do
      post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge_when_pipeline_succeeds", user)

      expect(response).to have_gitlab_http_status(404)
    end
  end

1088 1089 1090 1091 1092 1093
  describe 'Time tracking' do
    let(:issuable) { merge_request }

    include_examples 'time tracking endpoints', 'merge_request'
  end

1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
  def mr_with_later_created_and_updated_at_time
    merge_request
    merge_request.created_at += 1.hour
    merge_request.updated_at += 30.minutes
    merge_request.save
    merge_request
  end

  def mr_with_earlier_created_and_updated_at_time
    merge_request_closed
    merge_request_closed.created_at -= 1.hour
    merge_request_closed.updated_at -= 30.minutes
    merge_request_closed.save
    merge_request_closed
  end
V
Valeriy Sizov 已提交
1109
end