BigW Consortium Gitlab

pipelines_spec.rb 15.6 KB
Newer Older
1 2
require 'spec_helper'

3
describe 'Pipelines', :feature, :js do
4
  include WaitForVueResource
5 6 7

  let(:project) { create(:empty_project) }

8 9
  context 'when user is logged in' do
    let(:user) { create(:user) }
10

11 12 13
    before do
      login_as(user)
      project.team << [user, :developer]
14 15
    end

16 17 18 19 20 21 22 23 24
    describe 'GET /:project/pipelines' do
      let(:project) { create(:project) }

      let!(:pipeline) do
        create(
          :ci_empty_pipeline,
          project: project,
          ref: 'master',
          status: 'running',
25
          sha: project.commit.id
26
        )
27 28
      end

29 30 31 32 33 34 35
      context 'scope' do
        before do
          create(:ci_empty_pipeline, status: 'pending', project: project, sha: project.commit.id, ref: 'master')
          create(:ci_empty_pipeline, status: 'running', project: project, sha: project.commit.id, ref: 'master')
          create(:ci_empty_pipeline, status: 'created', project: project, sha: project.commit.id, ref: 'master')
          create(:ci_empty_pipeline, status: 'success', project: project, sha: project.commit.id, ref: 'master')
        end
36

37 38 39 40 41 42 43 44 45
        [:all, :running, :pending, :finished, :branches].each do |scope|
          context "when displaying #{scope}" do
            before do
              visit_project_pipelines(scope: scope)
            end

            it 'contains pipeline commit short SHA' do
              expect(page).to have_content(pipeline.short_sha)
            end
46

47 48 49
            it 'contains branch name' do
              expect(page).to have_content(pipeline.ref)
            end
50
          end
51
        end
Regis committed
52
      end
Kamil Trzcinski committed
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
      context 'header tabs' do
        before do
          visit namespace_project_pipelines_path(project.namespace, project)
          wait_for_vue_resource
        end

        it 'shows a tab for All pipelines and count' do
          expect(page.find('.js-pipelines-tab-all a').text).to include('All')
          expect(page.find('.js-pipelines-tab-all .badge').text).to include('1')
        end

        it 'shows a tab for Pending pipelines and count' do
          expect(page.find('.js-pipelines-tab-pending a').text).to include('Pending')
          expect(page.find('.js-pipelines-tab-pending .badge').text).to include('0')
        end

        it 'shows a tab for Running pipelines and count' do
          expect(page.find('.js-pipelines-tab-running a').text).to include('Running')
          expect(page.find('.js-pipelines-tab-running .badge').text).to include('1')
        end

        it 'shows a tab for Finished pipelines and count' do
          expect(page.find('.js-pipelines-tab-finished a').text).to include('Finished')
          expect(page.find('.js-pipelines-tab-finished .badge').text).to include('0')
        end

        it 'shows a tab for Branches' do
          expect(page.find('.js-pipelines-tab-branches a').text).to include('Branches')
        end

        it 'shows a tab for Tags' do
          expect(page.find('.js-pipelines-tab-tags a').text).to include('Tags')
        end
      end

89 90 91 92 93 94
      context 'when pipeline is cancelable' do
        let!(:build) do
          create(:ci_build, pipeline: pipeline,
                            stage: 'test',
                            commands: 'test')
        end
Kamil Trzcinski committed
95

96 97 98 99
        before do
          build.run
          visit_project_pipelines
        end
Kamil Trzcinski committed
100

101
        it 'indicates that pipeline can be canceled' do
102
          expect(page).to have_selector('.js-pipelines-cancel-button')
103 104
          expect(page).to have_selector('.ci-running')
        end
105

106
        context 'when canceling' do
107 108 109 110
          before do
            find('.js-pipelines-cancel-button').click
            wait_for_vue_resource
          end
111

112
          it 'indicated that pipelines was canceled' do
113
            expect(page).not_to have_selector('.js-pipelines-cancel-button')
114 115
            expect(page).to have_selector('.ci-canceled')
          end
116
        end
117
      end
118

119 120 121 122 123 124
      context 'when pipeline is retryable' do
        let!(:build) do
          create(:ci_build, pipeline: pipeline,
                            stage: 'test',
                            commands: 'test')
        end
125

126
        before do
127 128
          build.drop
          visit_project_pipelines
129
        end
130

131
        it 'indicates that pipeline can be retried' do
132
          expect(page).to have_selector('.js-pipelines-retry-button')
133 134
          expect(page).to have_selector('.ci-failed')
        end
135 136

        context 'when retrying' do
137 138 139 140
          before do
            find('.js-pipelines-retry-button').click
            wait_for_vue_resource
          end
141

142
          it 'shows running pipeline that is not retryable' do
143
            expect(page).not_to have_selector('.js-pipelines-retry-button')
144 145
            expect(page).to have_selector('.ci-running')
          end
146
        end
147 148
      end

149 150 151 152 153 154 155
      context 'when pipeline has configuration errors' do
        let(:pipeline) do
          create(:ci_pipeline, :invalid, project: project)
        end

        before { visit_project_pipelines }

156
        it 'contains badge that indicates errors' do
157 158 159 160 161 162 163 164 165 166
          expect(page).to have_content 'yaml invalid'
        end

        it 'contains badge with tooltip which contains error' do
          expect(pipeline).to have_yaml_errors
          expect(page).to have_selector(
            %Q{span[data-original-title="#{pipeline.yaml_errors}"]})
        end
      end

167 168 169
      context 'with manual actions' do
        let!(:manual) do
          create(:ci_build, :manual,
Regis committed
170
            pipeline: pipeline,
171 172 173
            name: 'manual build',
            stage: 'test',
            commands: 'test')
Regis committed
174
        end
175

176
        before { visit_project_pipelines }
177

178 179
        it 'has a dropdown with play button' do
          expect(page).to have_selector('.dropdown-toggle.btn.btn-default .icon-play')
180 181
        end

182 183 184
        it 'has link to the manual action' do
          find('.js-pipeline-dropdown-manual-actions').click

185
          expect(page).to have_button('manual build')
186
        end
187

188 189 190
        context 'when manual action was played' do
          before do
            find('.js-pipeline-dropdown-manual-actions').click
191
            click_button('manual build')
192
          end
193

194
          it 'enqueues manual action job' do
195
            expect(page).to have_selector('.js-pipeline-dropdown-manual-actions:disabled')
196
          end
197
        end
198 199
      end

200 201 202 203 204 205
      context 'for generic statuses' do
        context 'when running' do
          let!(:running) do
            create(:generic_commit_status,
              status: 'running',
              pipeline: pipeline,
206
              stage: 'test')
207
          end
208

209 210 211
          before { visit_project_pipelines }

          it 'is cancelable' do
212
            expect(page).to have_selector('.js-pipelines-cancel-button')
213
          end
214

215 216 217 218 219
          it 'has pipeline running' do
            expect(page).to have_selector('.ci-running')
          end

          context 'when canceling' do
220
            before { find('.js-pipelines-cancel-button').trigger('click') }
221

222
            it 'indicates that pipeline was canceled' do
223
              expect(page).not_to have_selector('.js-pipelines-cancel-button')
224 225
              expect(page).to have_selector('.ci-canceled')
            end
226
          end
227 228
        end

229 230 231 232 233 234 235 236 237 238 239 240 241
        context 'when failed' do
          let!(:status) do
            create(:generic_commit_status, :pending,
              pipeline: pipeline,
              stage: 'test')
          end

          before do
            status.drop
            visit_project_pipelines
          end

          it 'is not retryable' do
242
            expect(page).not_to have_selector('.js-pipelines-retry-button')
243 244 245 246 247
          end

          it 'has failed pipeline' do
            expect(page).to have_selector('.ci-failed')
          end
248 249 250
        end
      end

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
      context 'downloadable pipelines' do
        context 'with artifacts' do
          let!(:with_artifacts) do
            create(:ci_build, :artifacts, :success,
              pipeline: pipeline,
              name: 'rspec tests',
              stage: 'test')
          end

          before { visit_project_pipelines }

          it 'has artifats' do
            expect(page).to have_selector('.build-artifacts')
          end

          it 'has artifacts download dropdown' do
            find('.js-pipeline-dropdown-download').click

            expect(page).to have_link(with_artifacts.name)
          end
271 272 273 274 275 276 277 278

          it 'has download attribute on download links' do
            find('.js-pipeline-dropdown-download').click
            expect(page).to have_selector('a', text: 'Download')
            page.all('.build-artifacts a', text: 'Download').each do |link|
              expect(link[:download]).to eq ''
            end
          end
Regis committed
279
        end
Kamil Trzcinski committed
280

281 282 283 284 285 286 287
        context 'with artifacts expired' do
          let!(:with_artifacts_expired) do
            create(:ci_build, :artifacts_expired, :success,
              pipeline: pipeline,
              name: 'rspec',
              stage: 'test')
          end
288

289 290 291
          before { visit_project_pipelines }

          it { expect(page).not_to have_selector('.build-artifacts') }
292 293
        end

294 295 296 297 298 299 300 301 302
        context 'without artifacts' do
          let!(:without_artifacts) do
            create(:ci_build, :success,
              pipeline: pipeline,
              name: 'rspec',
              stage: 'test')
          end

          before { visit_project_pipelines }
303

304
          it { expect(page).not_to have_selector('.build-artifacts') }
305
        end
Kamil Trzcinski committed
306
      end
307

308
      context 'mini pipeline graph' do
309
        let!(:build) do
310 311 312
          create(:ci_build, :pending, pipeline: pipeline,
                                      stage: 'build',
                                      name: 'build')
Regis committed
313
        end
314

315
        before { visit_project_pipelines }
316

317 318 319 320 321
        it 'should render a mini pipeline graph' do
          expect(page).to have_selector('.js-mini-pipeline-graph')
          expect(page).to have_selector('.js-builds-dropdown-button')
        end

322
        context 'when clicking a stage badge' do
323 324
          it 'should open a dropdown' do
            find('.js-builds-dropdown-button').trigger('click')
325

326 327
            expect(page).to have_link build.name
          end
Kamil Trzcinski committed
328

329
          it 'should be possible to cancel pending build' do
330
            find('.js-builds-dropdown-button').trigger('click')
331
            find('a.js-ci-action-icon').trigger('click')
332

333 334
            expect(page).to have_content('canceled')
            expect(build.reload).to be_canceled
335 336
          end
        end
337 338 339 340 341 342 343 344 345 346 347 348

        context 'dropdown jobs list' do
          it 'should keep the dropdown open when the user ctr/cmd + clicks in the job name' do
            find('.js-builds-dropdown-button').trigger('click')

            execute_script('var e = $.Event("keydown", { keyCode: 64 }); $("body").trigger(e);')

            find('.mini-pipeline-graph-dropdown-item').trigger('click')

            expect(page).to have_selector('.js-ci-action-icon')
          end
        end
Kamil Trzcinski committed
349
      end
350 351 352

      context 'with pagination' do
        before do
353 354
          allow(Ci::Pipeline).to receive(:default_per_page).and_return(1)
          create(:ci_empty_pipeline,  project: project)
355 356 357 358 359 360
        end

        it 'should render pagination' do
          visit namespace_project_pipelines_path(project.namespace, project)
          wait_for_vue_resource

361
          expect(page).to have_selector('.gl-pagination')
362 363
        end

364
        it 'should render second page of pipelines' do
365 366 367
          visit namespace_project_pipelines_path(project.namespace, project, page: '2')
          wait_for_vue_resource

368
          expect(page).to have_selector('.gl-pagination .page', count: 2)
369 370
        end
      end
Kamil Trzcinski committed
371
    end
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 414
    describe 'GET /:project/pipelines/show' do
      let(:project) { create(:project) }

      let(:pipeline) do
        create(:ci_empty_pipeline,
              project: project,
              sha: project.commit.id,
              user: user)
      end

      before do
        create_build('build', 0, 'build', :success)
        create_build('test', 1, 'rspec 0:2', :pending)
        create_build('test', 1, 'rspec 1:2', :running)
        create_build('test', 1, 'spinach 0:2', :created)
        create_build('test', 1, 'spinach 1:2', :created)
        create_build('test', 1, 'audit', :created)
        create_build('deploy', 2, 'production', :created)

        create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3)

        visit namespace_project_pipeline_path(project.namespace, project, pipeline)
        wait_for_vue_resource
      end

      it 'shows a graph with grouped stages' do
        expect(page).to have_css('.js-pipeline-graph')

        # header
        expect(page).to have_text("##{pipeline.id}")
        expect(page).to have_selector(%Q(img[alt$="#{pipeline.user.name}'s avatar"]))
        expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user))

        # stages
        expect(page).to have_text('Build')
        expect(page).to have_text('Test')
        expect(page).to have_text('Deploy')
        expect(page).to have_text('External')

        # builds
        expect(page).to have_text('rspec')
        expect(page).to have_text('spinach')
Z.J. van de Weg committed
415
        expect(page).to have_text('rspec')
416 417 418 419 420 421 422 423 424
        expect(page).to have_text('production')
        expect(page).to have_text('jenkins')
      end

      def create_build(stage, stage_idx, name, status)
        create(:ci_build, pipeline: pipeline, stage: stage, stage_idx: stage_idx, name: name, status: status)
      end
    end

425 426 427 428 429
    describe 'POST /:project/pipelines' do
      let(:project) { create(:project) }

      before do
        visit new_namespace_project_pipeline_path(project.namespace, project)
430 431
      end

432 433 434 435 436 437 438 439
      context 'for valid commit', js: true do
        before do
          click_button project.default_branch

          page.within '.dropdown-menu' do
            click_link 'master'
          end
        end
440

441 442
        context 'with gitlab-ci.yml' do
          before { stub_ci_pipeline_to_return_yaml_file }
443

444 445 446 447
          it 'creates a new pipeline' do
            expect { click_on 'Create pipeline' }
              .to change { Ci::Pipeline.count }.by(1)
          end
448 449
        end

450 451
        context 'without gitlab-ci.yml' do
          before { click_on 'Create pipeline' }
452

453
          it { expect(page).to have_content('Missing .gitlab-ci.yml file') }
454 455
        end
      end
Regis committed
456
    end
Kamil Trzcinski committed
457

458 459
    describe 'Create pipelines' do
      let(:project) { create(:project) }
460

461 462 463
      before do
        visit new_namespace_project_pipeline_path(project.namespace, project)
      end
464

465 466
      describe 'new pipeline page' do
        it 'has field to add a new pipeline' do
467 468
          expect(page).to have_selector('.js-branch-select')
          expect(find('.js-branch-select')).to have_content project.default_branch
469
          expect(page).to have_content('Create for')
Regis committed
470
        end
Kamil Trzcinski committed
471
      end
Kamil Trzcinski committed
472

473 474
      describe 'find pipelines' do
        it 'shows filtered pipelines', js: true do
475
          click_button project.default_branch
476

477 478 479 480 481 482
          page.within '.dropdown-menu' do
            find('.dropdown-input-field').native.send_keys('fix')

            page.within '.dropdown-content' do
              expect(page).to have_content('fix')
            end
483 484
          end
        end
Kamil Trzcinski committed
485 486
      end
    end
487
  end
ubudzisz committed
488

489
  context 'when user is not logged in' do
ubudzisz committed
490
    before do
491
      visit namespace_project_pipelines_path(project.namespace, project)
ubudzisz committed
492 493
    end

494 495 496
    context 'when project is public' do
      let(:project) { create(:project, :public) }

497
      it { expect(page).to have_content 'Build with confidence' }
498
      it { expect(page).to have_http_status(:success) }
ubudzisz committed
499 500
    end

501 502
    context 'when project is private' do
      let(:project) { create(:project, :private) }
ubudzisz committed
503

504
      it { expect(page).to have_content 'You need to sign in' }
ubudzisz committed
505 506
    end
  end
507 508 509 510 511

  def visit_project_pipelines(**query)
    visit namespace_project_pipelines_path(project.namespace, project, query)
    wait_for_vue_resource
  end
512
end