diff --git a/app/serializers/job_entity.rb b/app/serializers/job_entity.rb index 0b19cb1695591818975753fe4c6d93739e9b117a..a0a66511b7b87b49d86d000d93e80258eeb4b7c5 100644 --- a/app/serializers/job_entity.rb +++ b/app/serializers/job_entity.rb @@ -9,7 +9,7 @@ class JobEntity < Grape::Entity expose :started?, as: :started expose :build_path do |build| - build.target_url || path_to(:namespace_project_job, build) + build_path(build) end expose :retry_path, if: -> (*) { retryable? } do |build| @@ -17,7 +17,11 @@ class JobEntity < Grape::Entity end expose :cancel_path, if: -> (*) { cancelable? } do |build| - path_to(:cancel_namespace_project_job, build) + path_to( + :cancel_namespace_project_job, + build, + { continue: { to: build_path(build) } } + ) end expose :play_path, if: -> (*) { playable? } do |build| @@ -60,8 +64,12 @@ class JobEntity < Grape::Entity build.detailed_status(request.current_user) end - def path_to(route, build) - send("#{route}_path", build.project.namespace, build.project, build) # rubocop:disable GitlabSecurity/PublicSend + def path_to(route, build, params = {}) + send("#{route}_path", build.project.namespace, build.project, build, params) # rubocop:disable GitlabSecurity/PublicSend + end + + def build_path(build) + build.target_url || path_to(:namespace_project_job, build) end def failed? diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index 2023d4b0bd0659f35df752efa09420422e102629..8eb01145ed51fb19dfc4b1787b5ac320210b92e9 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -152,11 +152,33 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(response).to have_gitlab_http_status(:ok) expect(response).to match_response_schema('job/job_details') expect(json_response['raw_path']).to match(%r{jobs/\d+/raw\z}) - expect(json_response.dig('merge_request', 'path')).to match(%r{merge_requests/\d+\z}) + expect(json_response['merge_request']['path']).to match(%r{merge_requests/\d+\z}) expect(json_response['new_issue_path']).to include('/issues/new') end end + context 'when job is running' do + context 'job is cancelable' do + let(:job) { create(:ci_build, :running, pipeline: pipeline) } + + it 'cancel_path is present with correct redirect' do + expect(response).to have_gitlab_http_status(:ok) + expect(response).to match_response_schema('job/job_details') + expect(json_response['cancel_path']).to include(CGI.escape(json_response['build_path'])) + end + end + + context 'with web terminal' do + let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) } + + it 'exposes the terminal path' do + expect(response).to have_gitlab_http_status(:ok) + expect(response).to match_response_schema('job/job_details') + expect(json_response['terminal_path']).to match(%r{/terminal}) + end + end + end + context 'when job has artifacts' do context 'with not expiry date' do let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) } @@ -185,16 +207,6 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do end end - context 'when job has terminal' do - let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) } - - it 'exposes the terminal path' do - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('job/job_details') - expect(json_response['terminal_path']).to match(%r{/terminal}) - end - end - context 'when job passed with no trace' do let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) } diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index b3bea92e635ad5cf8c4d42c98b37833b3824cdaa..5cb3f7c732f1a38b664e9427c81d85f66622e44b 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -198,6 +198,24 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do end end + context 'when job is running', :js do + let(:job) { create(:ci_build, :running, pipeline: pipeline) } + let(:job_url) { project_job_path(project, job) } + + before do + visit job_url + wait_for_requests + end + + context 'job is cancelable' do + it 'shows cancel button' do + click_link 'Cancel' + + expect(page.current_path).to eq(job_url) + end + end + end + context "Job from other project" do before do visit project_job_path(project, job2)