commit_controller_spec.rb 11.9 KB
Newer Older
S
Sean McGivern 已提交
1
require 'spec_helper'
2 3

describe Projects::CommitController do
4 5
  set(:project)  { create(:project, :repository) }
  set(:user)     { create(:user) }
6
  let(:commit)   { project.commit("master") }
S
Sean McGivern 已提交
7 8 9 10 11
  let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
  let(:master_pickable_commit)  { project.commit(master_pickable_sha) }

  before do
    sign_in(user)
12
    project.add_master(user)
S
Sean McGivern 已提交
13 14
  end

S
Sean McGivern 已提交
15
  describe 'GET show' do
16 17
    render_views

S
Sean McGivern 已提交
18 19
    def go(extra_params = {})
      params = {
20 21
        namespace_id: project.namespace,
        project_id: project
S
Sean McGivern 已提交
22 23 24 25 26
      }

      get :show, params.merge(extra_params)
    end

27 28
    context 'with valid id' do
      it 'responds with 200' do
S
Sean McGivern 已提交
29
        go(id: commit.id)
30 31 32 33 34 35 36

        expect(response).to be_ok
      end
    end

    context 'with invalid id' do
      it 'responds with 404' do
S
Sean McGivern 已提交
37
        go(id: commit.id.reverse)
38 39 40 41 42

        expect(response).to be_not_found
      end
    end

43
    it 'handles binary files' do
S
Sean McGivern 已提交
44 45 46 47 48 49
      go(id: TestEnv::BRANCH_SHA['binary-encoding'], format: 'html')

      expect(response).to be_success
    end

    shared_examples "export as" do |format|
50
      it "does generally work" do
S
Sean McGivern 已提交
51 52 53 54 55
        go(id: commit.id, format: format)

        expect(response).to be_success
      end

56
      it "generates it" do
S
Sean McGivern 已提交
57 58 59 60 61
        expect_any_instance_of(Commit).to receive(:"to_#{format}")

        go(id: commit.id, format: format)
      end

62
      it "renders it" do
S
Sean McGivern 已提交
63 64 65 66 67
        go(id: commit.id, format: format)

        expect(response.body).to eq(commit.send(:"to_#{format}"))
      end

68
      it "does not escape Html" do
69 70
        allow_any_instance_of(Commit).to receive(:"to_#{format}")
          .and_return('HTML entities &<>" ')
S
Sean McGivern 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

        go(id: commit.id, format: format)

        expect(response.body).not_to include('&amp;')
        expect(response.body).not_to include('&gt;')
        expect(response.body).not_to include('&lt;')
        expect(response.body).not_to include('&quot;')
      end
    end

    describe "as diff" do
      include_examples "export as", :diff
      let(:format) { :diff }

      it "should really only be a git diff" do
86
        go(id: '66eceea0db202bb39c4e445e8ca28689645366c5', format: format)
S
Sean McGivern 已提交
87 88 89 90

        expect(response.body).to start_with("diff --git")
      end

91
      it "is only be a git diff without whitespace changes" do
S
Sean McGivern 已提交
92 93 94
        go(id: '66eceea0db202bb39c4e445e8ca28689645366c5', format: format, w: 1)

        expect(response.body).to start_with("diff --git")
95 96 97

        # without whitespace option, there are more than 2 diff_splits for other formats
        diff_splits = assigns(:diffs).diff_files.first.diff.diff.split("\n")
S
Sean McGivern 已提交
98 99 100 101 102 103 104
        expect(diff_splits.length).to be <= 2
      end
    end

    describe "as patch" do
      include_examples "export as", :patch
      let(:format) { :patch }
105
      let(:commit2) { project.commit('498214de67004b1da3d820901307bed2a68a8ef6') }
S
Sean McGivern 已提交
106

107
      it "is a git email patch" do
108
        go(id: commit2.id, format: format)
S
Sean McGivern 已提交
109

110
        expect(response.body).to start_with("From #{commit2.id}")
S
Sean McGivern 已提交
111 112
      end

113
      it "contains a git diff" do
114
        go(id: commit2.id, format: format)
S
Sean McGivern 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127

        expect(response.body).to match(/^diff --git/)
      end
    end

    context 'commit that removes a submodule' do
      render_views

      let(:fork_project) { create(:forked_project_with_submodules, visibility_level: 20) }
      let(:commit) { fork_project.commit('remove-submodule') }

      it 'renders it' do
        get(:show,
128 129
            namespace_id: fork_project.namespace,
            project_id: fork_project,
S
Sean McGivern 已提交
130 131 132 133 134
            id: commit.id)

        expect(response).to be_success
      end
    end
135 136 137 138 139 140 141 142

    context 'in the context of a merge_request' do
      let(:merge_request) { create(:merge_request, source_project: project) }
      let(:commit) { merge_request.commits.first }

      it 'prepare diff notes in the context of the merge request' do
        go(id: commit.id, merge_request_iid: merge_request.iid)

M
micael.bergeron 已提交
143 144
        expect(assigns(:new_diff_note_attrs)).to eq({
                                                      noteable_type: 'MergeRequest',
145 146 147 148 149 150
                                                      noteable_id: merge_request.id,
                                                      commit_id: commit.id
                                                    })
        expect(response).to be_ok
      end
    end
S
Sean McGivern 已提交
151 152
  end

153 154
  describe 'GET branches' do
    it 'contains branch and tags information' do
155 156
      commit = project.commit('5937ac0a7beb003549fc5fd26fc247adbce4a52e')

S
Sean McGivern 已提交
157
      get(:branches,
158 159
          namespace_id: project.namespace,
          project_id: project,
S
Sean McGivern 已提交
160
          id: commit.id)
161

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
      expect(assigns(:branches)).to include('master', 'feature_conflict')
      expect(assigns(:branches_limit_exceeded)).to be_falsey
      expect(assigns(:tags)).to include('v1.1.0')
      expect(assigns(:tags_limit_exceeded)).to be_falsey
    end

    it 'returns :limit_exceeded when number of branches/tags reach a threshhold' do
      commit = project.commit('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
      allow_any_instance_of(Repository).to receive(:branch_count).and_return(1001)
      allow_any_instance_of(Repository).to receive(:tag_count).and_return(1001)

      get(:branches,
          namespace_id: project.namespace,
          project_id: project,
          id: commit.id)

      expect(assigns(:branches)).to eq([])
      expect(assigns(:branches_limit_exceeded)).to be_truthy
      expect(assigns(:tags)).to eq([])
      expect(assigns(:tags_limit_exceeded)).to be_truthy
S
Sean McGivern 已提交
182 183 184
    end
  end

S
Sean McGivern 已提交
185
  describe 'POST revert' do
S
Sean McGivern 已提交
186
    context 'when target branch is not provided' do
187
      it 'renders the 404 page' do
S
Sean McGivern 已提交
188
        post(:revert,
189 190
            namespace_id: project.namespace,
            project_id: project,
S
Sean McGivern 已提交
191 192 193
            id: commit.id)

        expect(response).not_to be_success
194
        expect(response).to have_gitlab_http_status(404)
S
Sean McGivern 已提交
195 196 197 198
      end
    end

    context 'when the revert was successful' do
199
      it 'redirects to the commits page' do
S
Sean McGivern 已提交
200
        post(:revert,
201 202
            namespace_id: project.namespace,
            project_id: project,
203
            start_branch: 'master',
S
Sean McGivern 已提交
204 205
            id: commit.id)

206
        expect(response).to redirect_to project_commits_path(project, 'master')
S
Sean McGivern 已提交
207 208 209 210 211 212 213
        expect(flash[:notice]).to eq('The commit has been successfully reverted.')
      end
    end

    context 'when the revert failed' do
      before do
        post(:revert,
214 215
            namespace_id: project.namespace,
            project_id: project,
216
            start_branch: 'master',
S
Sean McGivern 已提交
217 218 219
            id: commit.id)
      end

220
      it 'redirects to the commit page' do
S
Sean McGivern 已提交
221 222
        # Reverting a commit that has been already reverted.
        post(:revert,
223 224
            namespace_id: project.namespace,
            project_id: project,
225
            start_branch: 'master',
S
Sean McGivern 已提交
226 227
            id: commit.id)

228
        expect(response).to redirect_to project_commit_path(project, commit.id)
S
Sean McGivern 已提交
229 230 231 232 233
        expect(flash[:alert]).to match('Sorry, we cannot revert this commit automatically.')
      end
    end
  end

S
Sean McGivern 已提交
234
  describe 'POST cherry_pick' do
S
Sean McGivern 已提交
235
    context 'when target branch is not provided' do
236
      it 'renders the 404 page' do
S
Sean McGivern 已提交
237
        post(:cherry_pick,
238 239
            namespace_id: project.namespace,
            project_id: project,
S
Sean McGivern 已提交
240 241 242
            id: master_pickable_commit.id)

        expect(response).not_to be_success
243
        expect(response).to have_gitlab_http_status(404)
S
Sean McGivern 已提交
244 245 246 247
      end
    end

    context 'when the cherry-pick was successful' do
248
      it 'redirects to the commits page' do
S
Sean McGivern 已提交
249
        post(:cherry_pick,
250 251
            namespace_id: project.namespace,
            project_id: project,
252
            start_branch: 'master',
S
Sean McGivern 已提交
253 254
            id: master_pickable_commit.id)

255
        expect(response).to redirect_to project_commits_path(project, 'master')
S
Sean McGivern 已提交
256 257
        expect(flash[:notice]).to eq('The commit has been successfully cherry-picked.')
      end
258 259
    end

S
Sean McGivern 已提交
260 261 262
    context 'when the cherry_pick failed' do
      before do
        post(:cherry_pick,
263 264
            namespace_id: project.namespace,
            project_id: project,
265
            start_branch: 'master',
S
Sean McGivern 已提交
266 267 268
            id: master_pickable_commit.id)
      end

269
      it 'redirects to the commit page' do
S
Sean McGivern 已提交
270 271
        # Cherry-picking a commit that has been already cherry-picked.
        post(:cherry_pick,
272 273
            namespace_id: project.namespace,
            project_id: project,
274
            start_branch: 'master',
S
Sean McGivern 已提交
275 276
            id: master_pickable_commit.id)

277
        expect(response).to redirect_to project_commit_path(project, master_pickable_commit.id)
S
Sean McGivern 已提交
278 279 280 281 282
        expect(flash[:alert]).to match('Sorry, we cannot cherry-pick this commit automatically.')
      end
    end
  end

S
Sean McGivern 已提交
283
  describe 'GET diff_for_path' do
S
Sean McGivern 已提交
284 285
    def diff_for_path(extra_params = {})
      params = {
286 287
        namespace_id: project.namespace,
        project_id: project
S
Sean McGivern 已提交
288 289 290 291 292 293
      }

      get :diff_for_path, params.merge(extra_params)
    end

    let(:existing_path) { '.gitmodules' }
294
    let(:commit2) { project.commit('5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
S
Sean McGivern 已提交
295 296 297 298 299

    context 'when the commit exists' do
      context 'when the user has access to the project' do
        context 'when the path exists in the diff' do
          it 'enables diff notes' do
300
            diff_for_path(id: commit2.id, old_path: existing_path, new_path: existing_path)
S
Sean McGivern 已提交
301 302

            expect(assigns(:diff_notes_disabled)).to be_falsey
303
            expect(assigns(:new_diff_note_attrs)).to eq(noteable_type: 'Commit',
D
Douwe Maan 已提交
304
                                                        commit_id: commit2.id)
S
Sean McGivern 已提交
305 306 307
          end

          it 'only renders the diffs for the path given' do
308 309 310
            expect(controller).to receive(:render_diff_for_path).and_wrap_original do |meth, diffs|
              expect(diffs.diff_files.map(&:new_path)).to contain_exactly(existing_path)
              meth.call(diffs)
S
Sean McGivern 已提交
311 312
            end

313
            diff_for_path(id: commit2.id, old_path: existing_path, new_path: existing_path)
S
Sean McGivern 已提交
314 315 316 317
          end
        end

        context 'when the path does not exist in the diff' do
318 319 320
          before do
            diff_for_path(id: commit.id, old_path: existing_path.succ, new_path: existing_path.succ)
          end
S
Sean McGivern 已提交
321 322

          it 'returns a 404' do
323
            expect(response).to have_gitlab_http_status(404)
S
Sean McGivern 已提交
324 325 326 327 328 329 330
          end
        end
      end

      context 'when the user does not have access to the project' do
        before do
          project.team.truncate
331
          diff_for_path(id: commit.id, old_path: existing_path, new_path: existing_path)
S
Sean McGivern 已提交
332 333 334
        end

        it 'returns a 404' do
335
          expect(response).to have_gitlab_http_status(404)
S
Sean McGivern 已提交
336 337 338 339 340
        end
      end
    end

    context 'when the commit does not exist' do
341
      before do
342
        diff_for_path(id: commit.id.reverse, old_path: existing_path, new_path: existing_path)
343
      end
S
Sean McGivern 已提交
344 345

      it 'returns a 404' do
346
        expect(response).to have_gitlab_http_status(404)
S
Sean McGivern 已提交
347
      end
348 349
    end
  end
350 351 352 353

  describe 'GET pipelines' do
    def get_pipelines(extra_params = {})
      params = {
354 355
        namespace_id: project.namespace,
        project_id: project
356 357 358 359 360 361
      }

      get :pipelines, params.merge(extra_params)
    end

    context 'when the commit exists' do
362 363 364 365 366 367 368 369 370 371 372 373
      context 'when the commit has pipelines' do
        before do
          create(:ci_pipeline, project: project, sha: commit.id)
        end

        context 'when rendering a HTML format' do
          it 'shows pipelines' do
            get_pipelines(id: commit.id)

            expect(response).to be_ok
          end
        end
374

375 376 377 378 379
        context 'when rendering a JSON format' do
          it 'responds with serialized pipelines' do
            get_pipelines(id: commit.id, format: :json)

            expect(response).to be_ok
380 381
            expect(JSON.parse(response.body)['pipelines']).not_to be_empty
            expect(JSON.parse(response.body)['count']['all']).to eq 1
382
          end
383 384 385 386 387 388 389 390 391 392
        end
      end
    end

    context 'when the commit does not exist' do
      before do
        get_pipelines(id: 'e7a412c8da9f6d0081a633a4a402dde1c4694ebd')
      end

      it 'returns a 404' do
393
        expect(response).to have_gitlab_http_status(404)
394 395 396
      end
    end
  end
397
end