pipelines_spec.rb 25.3 KB
Newer Older
1 2
# frozen_string_literal: true

3 4
require 'spec_helper'

5
RSpec.describe 'Pipelines', :js do
Nathan Friend's avatar
Nathan Friend committed
6 7
  include ProjectForksHelper

8
  let(:project) { create(:project) }
9

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

13
    before do
14
      sign_in(user)
15

16
      project.add_developer(user)
17
      project.update!(auto_devops_attributes: { enabled: false })
18 19
    end

20
    describe 'GET /:project/-/pipelines' do
21
      let(:project) { create(:project, :repository) }
22 23 24 25 26 27 28

      let!(:pipeline) do
        create(
          :ci_empty_pipeline,
          project: project,
          ref: 'master',
          status: 'running',
29
          sha: project.commit.id
30
        )
31 32
      end

33 34 35 36 37 38 39
      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
40

41 42 43 44 45 46 47 48 49
        [: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
50

51 52 53
            it 'contains branch name' do
              expect(page).to have_content(pipeline.ref)
            end
54
          end
55
        end
Regis's avatar
Regis committed
56
      end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
57

58 59
      context 'header tabs' do
        before do
60
          visit project_pipelines_path(project)
61
          wait_for_requests
62 63 64
        end

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

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

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

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

        it 'updates content when tab is clicked' do
82
          page.find('.js-pipelines-tab-finished').click
83
          wait_for_requests
84
          expect(page).to have_content('There are currently no finished pipelines.')
85 86 87 88 89 90 91 92 93
        end
      end

      context 'navigation links' do
        before do
          visit project_pipelines_path(project)
          wait_for_requests
        end

94 95
        it 'renders "CI lint" link' do
          expect(page).to have_link('CI lint')
96 97
        end

98 99
        it 'renders "Run pipeline" link' do
          expect(page).to have_link('Run pipeline')
100 101 102
        end
      end

103 104 105
      context 'when pipeline is cancelable' do
        let!(:build) do
          create(:ci_build, pipeline: pipeline,
106
                            stage: 'test')
107
        end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
108

109 110 111 112
        before do
          build.run
          visit_project_pipelines
        end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
113

114
        it 'indicates that pipeline can be canceled' do
115
          expect(page).to have_selector('.js-pipelines-cancel-button')
116 117
          expect(page).to have_selector('.ci-running')
        end
118

119
        context 'when canceling' do
120
          before do
121
            find('.js-pipelines-cancel-button').click
122
            click_button 'Stop pipeline'
123
            wait_for_requests
124
          end
125

126
          it 'indicated that pipelines was canceled', :sidekiq_might_not_need_inline do
127
            expect(page).not_to have_selector('.js-pipelines-cancel-button')
128 129
            expect(page).to have_selector('.ci-canceled')
          end
130
        end
131
      end
132

133
      context 'when pipeline is retryable', :sidekiq_might_not_need_inline do
134 135
        let!(:build) do
          create(:ci_build, pipeline: pipeline,
136
                            stage: 'test')
137
        end
Regis's avatar
Regis committed
138

139
        before do
140 141
          build.drop
          visit_project_pipelines
142
        end
143

144
        it 'indicates that pipeline can be retried' do
145
          expect(page).to have_selector('.js-pipelines-retry-button')
146 147
          expect(page).to have_selector('.ci-failed')
        end
148 149

        context 'when retrying' do
150 151
          before do
            find('.js-pipelines-retry-button').click
152
            wait_for_requests
153
          end
154

155
          it 'shows running pipeline that is not retryable' do
156
            expect(page).not_to have_selector('.js-pipelines-retry-button')
157 158
            expect(page).to have_selector('.ci-running')
          end
159
        end
160 161
      end

Nathan Friend's avatar
Nathan Friend committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
      context 'when pipeline is detached merge request pipeline' do
        let(:merge_request) do
          create(:merge_request,
            :with_detached_merge_request_pipeline,
            source_project: source_project,
            target_project: target_project)
        end

        let!(:pipeline) { merge_request.all_pipelines.first }
        let(:source_project) { project }
        let(:target_project) { project }

        before do
          visit project_pipelines_path(source_project)
        end

178 179
        shared_examples_for 'detached merge request pipeline' do
          it 'shows pipeline information without pipeline ref', :sidekiq_might_not_need_inline do
Nathan Friend's avatar
Nathan Friend committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
            within '.pipeline-tags' do
              expect(page).to have_content('detached')
            end

            within '.branch-commit' do
              expect(page).to have_link(merge_request.iid,
                href: project_merge_request_path(project, merge_request))
            end

            within '.branch-commit' do
              expect(page).not_to have_link(pipeline.ref)
            end
          end
        end

195
        it_behaves_like 'detached merge request pipeline'
Nathan Friend's avatar
Nathan Friend committed
196 197 198 199

        context 'when source project is a forked project' do
          let(:source_project) { fork_project(project, user, repository: true) }

200
          it_behaves_like 'detached merge request pipeline'
Nathan Friend's avatar
Nathan Friend committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
        end
      end

      context 'when pipeline is merge request pipeline' do
        let(:merge_request) do
          create(:merge_request,
            :with_merge_request_pipeline,
            source_project: source_project,
            target_project: target_project,
            merge_sha: target_project.commit.sha)
        end

        let!(:pipeline) { merge_request.all_pipelines.first }
        let(:source_project) { project }
        let(:target_project) { project }

        before do
          visit project_pipelines_path(source_project)
        end

        shared_examples_for 'Correct merge request pipeline information' do
222
          it 'does not show detached tag for the pipeline, and shows the link of the merge request, and does not show the ref of the pipeline', :sidekiq_might_not_need_inline do
Nathan Friend's avatar
Nathan Friend committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
            within '.pipeline-tags' do
              expect(page).not_to have_content('detached')
            end

            within '.branch-commit' do
              expect(page).to have_link(merge_request.iid,
                href: project_merge_request_path(project, merge_request))
            end

            within '.branch-commit' do
              expect(page).not_to have_link(pipeline.ref)
            end
          end
        end

        it_behaves_like 'Correct merge request pipeline information'

        context 'when source project is a forked project' do
          let(:source_project) { fork_project(project, user, repository: true) }

          it_behaves_like 'Correct merge request pipeline information'
        end
      end

247 248 249 250 251
      context 'when pipeline has configuration errors' do
        let(:pipeline) do
          create(:ci_pipeline, :invalid, project: project)
        end

252 253 254
        before do
          visit_project_pipelines
        end
255

256
        it 'contains badge that indicates errors' do
257 258 259 260 261 262
          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(
263
            %Q{span[title="#{pipeline.yaml_errors}"]})
264
        end
265 266 267 268 269 270 271 272

        it 'contains badge that indicates failure reason' do
          expect(page).to have_content 'error'
        end

        it 'contains badge with tooltip which contains failure reason' do
          expect(pipeline.failure_reason?).to eq true
          expect(page).to have_selector(
273
            %Q{span[title="#{pipeline.present.failure_reason}"]})
274
        end
275 276
      end

277 278 279
      context 'with manual actions' do
        let!(:manual) do
          create(:ci_build, :manual,
Regis's avatar
Regis committed
280
            pipeline: pipeline,
281
            name: 'manual build',
282
            stage: 'test')
Regis's avatar
Regis committed
283
        end
284

285 286 287
        before do
          visit_project_pipelines
        end
288

289
        it 'has a dropdown with play button' do
290
          expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] [data-testid="play-icon"]')
291 292
        end

293
        it 'has link to the manual action' do
294
          find('[data-testid="pipelines-manual-actions-dropdown"]').click
295

296
          expect(page).to have_button('manual build')
297
        end
298

299 300
        context 'when manual action was played' do
          before do
301
            find('[data-testid="pipelines-manual-actions-dropdown"]').click
302
            click_button('manual build')
303
          end
304

305
          it 'enqueues manual action job' do
306
            expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] .gl-dropdown-toggle:disabled')
307
          end
308
        end
309 310
      end

Shinya Maeda's avatar
Shinya Maeda committed
311
      context 'when there is a delayed job' do
Shinya Maeda's avatar
Shinya Maeda committed
312 313 314
        let!(:delayed_job) do
          create(:ci_build, :scheduled,
            pipeline: pipeline,
315
            name: 'delayed job 1',
316
            stage: 'test')
Shinya Maeda's avatar
Shinya Maeda committed
317 318 319 320 321 322
        end

        before do
          visit_project_pipelines
        end

Shinya Maeda's avatar
Shinya Maeda committed
323
        it 'has a dropdown for actionable jobs' do
324
          expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] [data-testid="play-icon"]')
Shinya Maeda's avatar
Shinya Maeda committed
325 326
        end

Shinya Maeda's avatar
Shinya Maeda committed
327
        it "has link to the delayed job's action" do
328
          find('[data-testid="pipelines-manual-actions-dropdown"]').click
Shinya Maeda's avatar
Shinya Maeda committed
329

330
          time_diff = [0, delayed_job.scheduled_at - Time.now].max
331
          expect(page).to have_button('delayed job 1')
332 333 334 335 336 337 338
          expect(page).to have_content(Time.at(time_diff).utc.strftime("%H:%M:%S"))
        end

        context 'when delayed job is expired already' do
          let!(:delayed_job) do
            create(:ci_build, :expired_scheduled,
              pipeline: pipeline,
339
              name: 'delayed job 1',
340
              stage: 'test')
341 342 343
          end

          it "shows 00:00:00 as the remaining time" do
344
            find('[data-testid="pipelines-manual-actions-dropdown"]').click
345

Shinya Maeda's avatar
Shinya Maeda committed
346
            expect(page).to have_content("00:00:00")
347
          end
Shinya Maeda's avatar
Shinya Maeda committed
348 349
        end

Shinya Maeda's avatar
Shinya Maeda committed
350
        context 'when user played a delayed job immediately' do
Shinya Maeda's avatar
Shinya Maeda committed
351
          before do
352
            find('[data-testid="pipelines-manual-actions-dropdown"]').click
353
            page.accept_confirm { click_button('delayed job 1') }
Shinya Maeda's avatar
Shinya Maeda committed
354
            wait_for_requests
Shinya Maeda's avatar
Shinya Maeda committed
355 356
          end

Shinya Maeda's avatar
Shinya Maeda committed
357 358
          it 'enqueues the delayed job', :js do
            expect(delayed_job.reload).to be_pending
Shinya Maeda's avatar
Shinya Maeda committed
359 360 361 362
          end
        end
      end

363
      context 'for generic statuses' do
Tiger's avatar
Tiger committed
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
        context 'when preparing' do
          let!(:pipeline) do
            create(:ci_empty_pipeline,
              status: 'preparing', project: project)
          end

          let!(:status) do
            create(:generic_commit_status,
              :preparing, pipeline: pipeline)
          end

          before do
            visit_project_pipelines
          end

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

          it 'shows the pipeline as preparing' do
            expect(page).to have_selector('.ci-preparing')
          end
        end

388 389 390 391 392
        context 'when running' do
          let!(:running) do
            create(:generic_commit_status,
              status: 'running',
              pipeline: pipeline,
393
              stage: 'test')
394
          end
395

396 397 398
          before do
            visit_project_pipelines
          end
399 400

          it 'is cancelable' do
401
            expect(page).to have_selector('.js-pipelines-cancel-button')
402
          end
403

404 405 406 407 408
          it 'has pipeline running' do
            expect(page).to have_selector('.ci-running')
          end

          context 'when canceling' do
409
            before do
410
              find('.js-pipelines-cancel-button').click
411
              click_button 'Stop pipeline'
412
            end
413

414
            it 'indicates that pipeline was canceled', :sidekiq_might_not_need_inline do
415
              expect(page).not_to have_selector('.js-pipelines-cancel-button')
416 417
              expect(page).to have_selector('.ci-canceled')
            end
418
          end
419 420
        end

421 422 423 424 425 426 427 428 429 430 431 432 433
        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
434
            expect(page).not_to have_selector('.js-pipelines-retry-button')
435 436
          end

437
          it 'has failed pipeline', :sidekiq_might_not_need_inline do
438 439
            expect(page).to have_selector('.ci-failed')
          end
440 441 442
        end
      end

443 444 445
      context 'downloadable pipelines' do
        context 'with artifacts' do
          let!(:with_artifacts) do
446
            build = create(:ci_build, :success,
447 448 449
              pipeline: pipeline,
              name: 'rspec tests',
              stage: 'test')
450 451

            create(:ci_job_artifact, :codequality, job: build)
452 453
          end

454 455 456
          before do
            visit_project_pipelines
          end
457

458 459
          it 'has artifacts dropdown' do
            expect(page).to have_selector('[data-testid="pipeline-multi-actions-dropdown"]')
460
          end
Regis's avatar
Regis committed
461
        end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
462

463 464
        context 'with artifacts expired' do
          let!(:with_artifacts_expired) do
465
            create(:ci_build, :expired, :success,
466 467 468 469
              pipeline: pipeline,
              name: 'rspec',
              stage: 'test')
          end
470

471 472 473
          before do
            visit_project_pipelines
          end
474

475
          it { expect(page).not_to have_selector('[data-testid="artifact-item"]') }
476 477
        end

478 479 480 481 482 483 484 485
        context 'without artifacts' do
          let!(:without_artifacts) do
            create(:ci_build, :success,
              pipeline: pipeline,
              name: 'rspec',
              stage: 'test')
          end

486 487 488
          before do
            visit_project_pipelines
          end
489

490
          it { expect(page).not_to have_selector('[data-testid="artifact-item"]') }
491
        end
492 493 494 495 496 497 498 499

        context 'with trace artifact' do
          before do
            create(:ci_build, :success, :trace_artifact, pipeline: pipeline)

            visit_project_pipelines
          end

Shinya Maeda's avatar
Shinya Maeda committed
500
          it 'does not show trace artifact as artifacts' do
501
            expect(page).not_to have_selector('[data-testid="artifact-item"]')
502 503
          end
        end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
504
      end
505

506 507 508 509 510 511
      context 'mini pipeline graph' do
        let!(:build) do
          create(:ci_build, :pending, pipeline: pipeline,
                                      stage: 'build',
                                      name: 'build')
        end
512

513
        dropdown_selector = '[data-testid="mini-pipeline-graph-dropdown"]'
514

515 516 517
        before do
          visit_project_pipelines
        end
518

519
        it 'renders a mini pipeline graph' do
Miguel Rincon's avatar
Miguel Rincon committed
520
          expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
521 522
          expect(page).to have_selector(dropdown_selector)
        end
523

524 525 526
        context 'when clicking a stage badge' do
          it 'opens a dropdown' do
            find(dropdown_selector).click
527

528 529
            expect(page).to have_link build.name
          end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
530

531 532 533 534
          it 'is possible to cancel pending build' do
            find(dropdown_selector).click
            find('.js-ci-action').click
            wait_for_requests
535

536
            expect(build.reload).to be_canceled
537
          end
538
        end
539

540 541 542 543 544 545
        context 'for a failed pipeline' do
          let!(:build) do
            create(:ci_build, :failed, pipeline: pipeline,
                                      stage: 'build',
                                      name: 'build')
          end
546

547 548
          it 'displays the failure reason' do
            find(dropdown_selector).click
549

550 551 552
            within('.js-builds-dropdown-list') do
              build_element = page.find('.mini-pipeline-graph-dropdown-item')
              expect(build_element['title']).to eq('build - failed - (unknown failure)')
553 554
            end
          end
555
        end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
556
      end
557 558 559

      context 'with pagination' do
        before do
560
          allow(Ci::Pipeline).to receive(:default_per_page).and_return(1)
561
          create(:ci_empty_pipeline, project: project)
562 563
        end

564
        it 'renders pagination' do
565
          visit project_pipelines_path(project)
566
          wait_for_requests
567

568
          expect(page).to have_selector('.gl-pagination')
569 570
        end

571
        it 'renders second page of pipelines' do
572
          visit project_pipelines_path(project, page: '2')
573
          wait_for_requests
574

575
          expect(page).to have_selector('.gl-pagination .page-link', count: 4)
576
        end
577

578
        it 'shows updated content' do
579 580
          visit project_pipelines_path(project)
          wait_for_requests
581
          page.find('.page-link.next-page-item').click
582

583
          expect(page).to have_selector('.gl-pagination .page-link', count: 4)
584
        end
585
      end
Jose Vargas's avatar
Jose Vargas committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605

      context 'with pipeline key selection' do
        before do
          visit project_pipelines_path(project)
          wait_for_requests
        end

        it 'changes the Pipeline ID column for Pipeline IID' do
          page.find('[data-testid="pipeline-key-dropdown"]').click

          within '.gl-new-dropdown-contents' do
            dropdown_options = page.find_all '.gl-new-dropdown-item'

            dropdown_options[1].click
          end

          expect(page.find('[data-testid="pipeline-th"]')).to have_content 'Pipeline IID'
          expect(page.find('[data-testid="pipeline-url-link"]')).to have_content "##{pipeline.iid}"
        end
      end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
606
    end
607

608
    describe 'GET /:project/-/pipelines/show' do
609
      let(:project) { create(:project, :repository) }
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628

      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)

629
        visit project_pipeline_path(project, pipeline)
630
        wait_for_requests
631 632 633 634 635 636 637
      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}")
638
        expect(page).to have_selector(%Q(img[src="#{pipeline.user.avatar_url}"]))
639 640 641 642 643 644 645 646 647 648 649
        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's avatar
Z.J. van de Weg committed
650
        expect(page).to have_text('rspec')
651 652 653 654 655 656 657 658 659
        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

660
    describe 'POST /:project/-/pipelines' do
661
      let(:project) { create(:project, :repository) }
662 663

      before do
664
        visit new_project_pipeline_path(project)
665 666
      end

667
      context 'for valid commit', :js do
668 669
        before do
          click_button project.default_branch
670 671 672 673
          wait_for_requests

          find('p', text: 'master').click
          wait_for_requests
674
        end
675

676
        context 'with gitlab-ci.yml', :js do
677 678 679
          before do
            stub_ci_pipeline_to_return_yaml_file
          end
680

681
          it 'creates a new pipeline' do
682
            expect do
683
              click_on 'Run pipeline'
684 685
              wait_for_requests
            end
686
              .to change { Ci::Pipeline.count }.by(1)
687 688

            expect(Ci::Pipeline.last).to be_web
689
          end
690 691 692

          context 'when variables are specified' do
            it 'creates a new pipeline with variables' do
693
              page.within(find("[data-testid='ci-variable-row']")) do
694 695
                find("[data-testid='pipeline-form-ci-variable-key']").set('key_name')
                find("[data-testid='pipeline-form-ci-variable-value']").set('value')
696 697
              end

698
              expect do
699
                click_on 'Run pipeline'
700 701
                wait_for_requests
              end
702 703 704 705 706 707
                .to change { Ci::Pipeline.count }.by(1)

              expect(Ci::Pipeline.last.variables.map { |var| var.slice(:key, :secret_value) })
                .to eq [{ key: "key_name", secret_value: "value" }.with_indifferent_access]
            end
          end
708 709
        end

710
        context 'without gitlab-ci.yml' do
711
          before do
712
            click_on 'Run pipeline'
713
            wait_for_requests
714
          end
715

716
          it { expect(page).to have_content('Missing CI config file') }
717 718 719
          it 'creates a pipeline after first request failed and a valid gitlab-ci.yml file is available when trying again' do
            stub_ci_pipeline_to_return_yaml_file

720
            expect do
721
              click_on 'Run pipeline'
722
              wait_for_requests
723 724 725
            end
              .to change { Ci::Pipeline.count }.by(1)
          end
726 727
        end
      end
Regis's avatar
Regis committed
728
    end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
729

730 731 732 733 734
    describe 'Reset runner caches' do
      let(:project) { create(:project, :repository) }

      before do
        create(:ci_empty_pipeline, status: 'success', project: project, sha: project.commit.id, ref: 'master')
735
        project.add_maintainer(user)
736 737 738 739
        visit project_pipelines_path(project)
      end

      it 'has a clear caches button' do
740
        expect(page).to have_button 'Clear runner caches'
741 742 743 744 745
      end

      describe 'user clicks the button' do
        context 'when project already has jobs_cache_index' do
          before do
746
            project.update!(jobs_cache_index: 1)
747 748 749
          end

          it 'increments jobs_cache_index' do
750
            click_button 'Clear runner caches'
751
            wait_for_requests
752 753 754 755 756 757
            expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
          end
        end

        context 'when project does not have jobs_cache_index' do
          it 'sets jobs_cache_index to 1' do
758
            click_button 'Clear runner caches'
759
            wait_for_requests
760 761 762 763 764
            expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
          end
        end
      end
    end
765

766 767 768 769 770 771 772 773 774
    describe 'Run Pipelines' do
      let(:project) { create(:project, :repository) }

      before do
        visit new_project_pipeline_path(project)
      end

      describe 'new pipeline page' do
        it 'has field to add a new pipeline' do
775 776
          expect(page).to have_selector('[data-testid="ref-select"]')
          expect(find('[data-testid="ref-select"]')).to have_content project.default_branch
777 778 779 780 781 782 783 784
          expect(page).to have_content('Run for')
        end
      end

      describe 'find pipelines' do
        it 'shows filtered pipelines', :js do
          click_button project.default_branch

785 786
          page.within '[data-testid="ref-select"]' do
            find('[data-testid="search-refs"]').native.send_keys('fix')
787

788
            page.within '.gl-new-dropdown-contents' do
789 790 791 792 793 794 795
              expect(page).to have_content('fix')
            end
          end
        end
      end
    end

796 797 798 799 800 801 802 803
    describe 'Empty State' do
      let(:project) { create(:project, :repository) }

      before do
        visit project_pipelines_path(project)
      end

      it 'renders empty state' do
804
        expect(page).to have_content 'Use a sample CI/CD template'
805 806
      end
    end
807
  end
ubudzisz's avatar
ubudzisz committed
808

809
  context 'when user is not logged in' do
ubudzisz's avatar
ubudzisz committed
810
    before do
811
      project.update!(auto_devops_attributes: { enabled: false })
812
      visit project_pipelines_path(project)
ubudzisz's avatar
ubudzisz committed
813 814
    end

815
    context 'when project is public' do
816
      let(:project) { create(:project, :public, :repository) }
817

818 819 820
      context 'without pipelines' do
        it { expect(page).to have_content 'This project is not currently set up to run pipelines.' }
      end
ubudzisz's avatar
ubudzisz committed
821 822
    end

823
    context 'when project is private' do
824
      let(:project) { create(:project, :private, :repository) }
ubudzisz's avatar
ubudzisz committed
825

826 827 828 829
      it 'redirects the user to sign_in and displays the flash alert' do
        expect(page).to have_content 'You need to sign in'
        expect(page.current_path).to eq("/users/sign_in")
      end
ubudzisz's avatar
ubudzisz committed
830 831
    end
  end
832 833

  def visit_project_pipelines(**query)
834
    visit project_pipelines_path(project, query)
835
    wait_for_requests
836
  end
837
end