diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2019-09-11 12:06:33 +0300 |
---|---|---|
committer | Kushal Pandya <kushalspandya@gmail.com> | 2019-09-11 12:06:33 +0300 |
commit | 48b98b5898e15ab4bb1db47e201fef8db68dc34d (patch) | |
tree | 70edcf4953d88d542243fe1d288ff249c02c9d9f /spec | |
parent | bfaa96d586668678893e295062495f2c35b73c2a (diff) |
Enables Run Pipeline button to be rendered
In the Merge Request view, under pipelines tab
the user can see a run pipeline button
Adds axios post request to button click
Adds the logic to handle the user click,
refresh the table and disable the button while thee
request is being made
Updates UI for desktop and mobile
Adds specs
Regenerates potfile
Follow-up after review
Uses .finally to avoid code repetition
Diffstat (limited to 'spec')
-rw-r--r-- | spec/features/merge_request/user_sees_pipelines_spec.rb | 32 | ||||
-rw-r--r-- | spec/javascripts/commit/pipelines/pipelines_spec.js | 167 | ||||
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 16 | ||||
-rw-r--r-- | spec/requests/api/merge_requests_spec.rb | 64 | ||||
-rw-r--r-- | spec/services/merge_requests/create_pipeline_service_spec.rb | 4 |
5 files changed, 250 insertions, 33 deletions
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb index f04317a59ee..7a8b938486a 100644 --- a/spec/features/merge_request/user_sees_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_spec.rb @@ -45,6 +45,38 @@ describe 'Merge request > User sees pipelines', :js do expect(page.find('.ci-widget')).to have_text("Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.") end + + context 'with a detached merge request pipeline' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } + + it 'displays the Run Pipeline button' do + visit project_merge_request_path(project, merge_request) + + page.within('.merge-request-tabs') do + click_link('Pipelines') + end + + wait_for_requests + + expect(page.find('.js-run-mr-pipeline')).to have_text('Run Pipeline') + end + end + + context 'with a merged results pipeline' do + let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) } + + it 'displays the Run Pipeline button' do + visit project_merge_request_path(project, merge_request) + + page.within('.merge-request-tabs') do + click_link('Pipelines') + end + + wait_for_requests + + expect(page.find('.js-run-mr-pipeline')).to have_text('Run Pipeline') + end + end end context 'without pipelines' do diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js index fec01b1f0a3..46aca2b7f03 100644 --- a/spec/javascripts/commit/pipelines/pipelines_spec.js +++ b/spec/javascripts/commit/pipelines/pipelines_spec.js @@ -1,6 +1,7 @@ import Vue from 'vue'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; +import Api from '~/api'; import pipelinesTable from '~/commit/pipelines/pipelines_table.vue'; import mountComponent from 'spec/helpers/vue_mount_component_helper'; @@ -10,6 +11,13 @@ describe('Pipelines table in Commits and Merge requests', function() { let PipelinesTable; let mock; let vm; + const props = { + endpoint: 'endpoint.json', + helpPagePath: 'foo', + emptyStateSvgPath: 'foo', + errorStateSvgPath: 'foo', + autoDevopsHelpPath: 'foo', + }; preloadFixtures(jsonFixtureName); @@ -32,13 +40,7 @@ describe('Pipelines table in Commits and Merge requests', function() { beforeEach(function() { mock.onGet('endpoint.json').reply(200, []); - vm = mountComponent(PipelinesTable, { - endpoint: 'endpoint.json', - helpPagePath: 'foo', - emptyStateSvgPath: 'foo', - errorStateSvgPath: 'foo', - autoDevopsHelpPath: 'foo', - }); + vm = mountComponent(PipelinesTable, props); }); it('should render the empty state', function(done) { @@ -54,13 +56,7 @@ describe('Pipelines table in Commits and Merge requests', function() { describe('with pipelines', () => { beforeEach(() => { mock.onGet('endpoint.json').reply(200, [pipeline]); - vm = mountComponent(PipelinesTable, { - endpoint: 'endpoint.json', - helpPagePath: 'foo', - emptyStateSvgPath: 'foo', - errorStateSvgPath: 'foo', - autoDevopsHelpPath: 'foo', - }); + vm = mountComponent(PipelinesTable, props); }); it('should render a table with the received pipelines', done => { @@ -111,30 +107,145 @@ describe('Pipelines table in Commits and Merge requests', function() { done(); }); - vm = mountComponent(PipelinesTable, { - endpoint: 'endpoint.json', - helpPagePath: 'foo', - emptyStateSvgPath: 'foo', - errorStateSvgPath: 'foo', - autoDevopsHelpPath: 'foo', - }); + vm = mountComponent(PipelinesTable, props); element.appendChild(vm.$el); }); }); }); + describe('run pipeline button', () => { + let pipelineCopy; + + beforeEach(() => { + pipelineCopy = Object.assign({}, pipeline); + }); + + describe('when latest pipeline has detached flag and canRunPipeline is true', () => { + it('renders the run pipeline button', done => { + pipelineCopy.flags.detached_merge_request_pipeline = true; + pipelineCopy.flags.merge_request_pipeline = true; + + mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + + vm = mountComponent( + PipelinesTable, + Object.assign({}, props, { + canRunPipeline: true, + }), + ); + + setTimeout(() => { + expect(vm.$el.querySelector('.js-run-mr-pipeline')).not.toBeNull(); + done(); + }); + }); + }); + + describe('when latest pipeline has detached flag and canRunPipeline is false', () => { + it('does not render the run pipeline button', done => { + pipelineCopy.flags.detached_merge_request_pipeline = true; + pipelineCopy.flags.merge_request_pipeline = true; + + mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + + vm = mountComponent( + PipelinesTable, + Object.assign({}, props, { + canRunPipeline: false, + }), + ); + + setTimeout(() => { + expect(vm.$el.querySelector('.js-run-mr-pipeline')).toBeNull(); + done(); + }); + }); + }); + + describe('when latest pipeline does not have detached flag and canRunPipeline is true', () => { + it('does not render the run pipeline button', done => { + pipelineCopy.flags.detached_merge_request_pipeline = false; + pipelineCopy.flags.merge_request_pipeline = false; + + mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + + vm = mountComponent( + PipelinesTable, + Object.assign({}, props, { + canRunPipeline: true, + }), + ); + + setTimeout(() => { + expect(vm.$el.querySelector('.js-run-mr-pipeline')).toBeNull(); + done(); + }); + }); + }); + + describe('when latest pipeline does not have detached flag and merge_request_pipeline is true', () => { + it('does not render the run pipeline button', done => { + pipelineCopy.flags.detached_merge_request_pipeline = false; + pipelineCopy.flags.merge_request_pipeline = true; + + mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + + vm = mountComponent( + PipelinesTable, + Object.assign({}, props, { + canRunPipeline: false, + }), + ); + + setTimeout(() => { + expect(vm.$el.querySelector('.js-run-mr-pipeline')).toBeNull(); + done(); + }); + }); + }); + + describe('on click', () => { + beforeEach(() => { + pipelineCopy.flags.detached_merge_request_pipeline = true; + + mock.onGet('endpoint.json').reply(200, [pipelineCopy]); + + vm = mountComponent( + PipelinesTable, + Object.assign({}, props, { + canRunPipeline: true, + projectId: '5', + mergeRequestId: 3, + }), + ); + }); + + it('updates the loading state', done => { + spyOn(Api, 'postMergeRequestPipeline').and.returnValue(Promise.resolve()); + + setTimeout(() => { + vm.$el.querySelector('.js-run-mr-pipeline').click(); + + vm.$nextTick(() => { + expect(vm.state.isRunningMergeRequestPipeline).toBe(true); + + setTimeout(() => { + expect(vm.state.isRunningMergeRequestPipeline).toBe(false); + + done(); + }); + }); + }); + }); + }); + }); + describe('unsuccessfull request', () => { beforeEach(() => { mock.onGet('endpoint.json').reply(500, []); - vm = mountComponent(PipelinesTable, { - endpoint: 'endpoint.json', - helpPagePath: 'foo', - emptyStateSvgPath: 'foo', - errorStateSvgPath: 'foo', - autoDevopsHelpPath: 'foo', - }); + vm = mountComponent(PipelinesTable, props); }); it('should render error state', function(done) { diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 146e479adef..d5ad70194cb 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -579,14 +579,22 @@ describe Ci::Pipeline, :mailer do end describe 'Validations for merge request pipelines' do - let(:pipeline) { build(:ci_pipeline, source: source, merge_request: merge_request) } + let(:pipeline) do + build(:ci_pipeline, source: source, merge_request: merge_request) + end + + let(:merge_request) do + create(:merge_request, + source_project: project, + source_branch: 'feature', + target_project: project, + target_branch: 'master') + end context 'when source is merge request' do let(:source) { :merge_request_event } context 'when merge request is specified' do - let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_project: project, target_branch: 'master') } - it { expect(pipeline).to be_valid } end @@ -601,8 +609,6 @@ describe Ci::Pipeline, :mailer do let(:source) { :web } context 'when merge request is specified' do - let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_project: project, target_branch: 'master') } - it { expect(pipeline).not_to be_valid } end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 15d6db42760..8179da2f97c 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -1033,6 +1033,70 @@ describe API::MergeRequests do end end + describe 'POST /projects/:id/merge_requests/:merge_request_iid/pipelines' do + before do + allow_any_instance_of(Ci::Pipeline) + .to receive(:ci_yaml_file) + .and_return(YAML.dump({ + rspec: { + script: 'ls', + only: ['merge_requests'] + } + })) + end + + let(:project) do + create(:project, :private, :repository, + creator: user, + namespace: user.namespace, + only_allow_merge_if_pipeline_succeeds: false) + end + + let(:merge_request) do + create(:merge_request, :with_detached_merge_request_pipeline, + milestone: milestone1, + author: user, + assignees: [user], + source_project: project, + target_project: project, + title: 'Test', + created_at: base_time) + end + + let(:merge_request_iid) { merge_request.iid } + let(:authenticated_user) { user } + + let(:request) do + post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/pipelines", authenticated_user) + end + + context 'when authorized' do + it 'creates and returns the new Pipeline' do + expect { request }.to change(Ci::Pipeline, :count).by(1) + expect(response).to have_gitlab_http_status(200) + expect(json_response).to be_a Hash + end + end + + context 'when unauthorized' do + let(:authenticated_user) { create(:user) } + + it 'responds with a blank 404' do + expect { request }.not_to change(Ci::Pipeline, :count) + expect(response).to have_gitlab_http_status(404) + end + end + + context 'when the merge request does not exist' do + let(:merge_request_iid) { 777 } + + it 'responds with a blank 404' do + expect { request }.not_to change(Ci::Pipeline, :count) + expect(response).to have_gitlab_http_status(404) + end + end + end + describe 'POST /projects/:id/merge_requests' do context 'support for deprecated assignee_id' do let(:params) do diff --git a/spec/services/merge_requests/create_pipeline_service_spec.rb b/spec/services/merge_requests/create_pipeline_service_spec.rb index 9479439bde8..576e8498e4d 100644 --- a/spec/services/merge_requests/create_pipeline_service_spec.rb +++ b/spec/services/merge_requests/create_pipeline_service_spec.rb @@ -38,6 +38,10 @@ describe MergeRequests::CreatePipelineService do expect(subject).to be_detached_merge_request_pipeline end + it 'defaults to merge_request_event' do + expect(subject.source).to eq('merge_request_event') + end + context 'when service is called multiple times' do it 'creates a pipeline once' do expect do |