edc46ce3e4
* upstream/master: (460 commits) Center dropdown for pipeline's mini graph Documentation bugfix of invalid JSON payload example of Create a commit with multiple files and actions Fix filename method of GitlabUploader to return always real filename Ignore CVE-2017-5029 in Nokogiri Refactor atom builder by using xml.atom layout Let PhantomJS load local images Add a changelog entry Only add a description change note when no tasks are updated Doc: Add the need to upgrade to Go 1.8.3 in the 9.1->9.2 documentation as the upgrade fails with Go 1.5 (installed with Gitlab 8.1) Use gitaly 0.11.2 Add the ability to perform background migrations Always render warnings icon in orange Fix a few translation for zh_TW Improve Job detail view to make it refreshed in real-time instead of reloading Attempts to run RSpec tests twice (1 retry) ignore name validation on importing Only show hover state on links and buttons Use vue files for navigation tabs and buttons doc: add example of scheduler when Add test for u2f helper and changelog entry ...
439 lines
11 KiB
Ruby
439 lines
11 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe Projects::JobsController do
|
|
include ApiHelpers
|
|
|
|
let(:project) { create(:empty_project, :public) }
|
|
let(:pipeline) { create(:ci_pipeline, project: project) }
|
|
let(:user) { create(:user) }
|
|
|
|
describe 'GET index' do
|
|
context 'when scope is pending' do
|
|
before do
|
|
create(:ci_build, :pending, pipeline: pipeline)
|
|
|
|
get_index(scope: 'pending')
|
|
end
|
|
|
|
it 'has only pending builds' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(assigns(:builds).first.status).to eq('pending')
|
|
end
|
|
end
|
|
|
|
context 'when scope is running' do
|
|
before do
|
|
create(:ci_build, :running, pipeline: pipeline)
|
|
|
|
get_index(scope: 'running')
|
|
end
|
|
|
|
it 'has only running jobs' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(assigns(:builds).first.status).to eq('running')
|
|
end
|
|
end
|
|
|
|
context 'when scope is finished' do
|
|
before do
|
|
create(:ci_build, :success, pipeline: pipeline)
|
|
|
|
get_index(scope: 'finished')
|
|
end
|
|
|
|
it 'has only finished jobs' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(assigns(:builds).first.status).to eq('success')
|
|
end
|
|
end
|
|
|
|
context 'when page is specified' do
|
|
let(:last_page) { project.builds.page.total_pages }
|
|
|
|
context 'when page number is eligible' do
|
|
before do
|
|
create_list(:ci_build, 2, pipeline: pipeline)
|
|
|
|
get_index(page: last_page.to_param)
|
|
end
|
|
|
|
it 'redirects to the page' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(assigns(:builds).current_page).to eq(last_page)
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'number of queries' do
|
|
before do
|
|
Ci::Build::AVAILABLE_STATUSES.each do |status|
|
|
create_job(status, status)
|
|
end
|
|
end
|
|
|
|
it 'verifies number of queries', :request_store do
|
|
recorded = ActiveRecord::QueryRecorder.new { get_index }
|
|
expect(recorded.count).to be_within(5).of(7)
|
|
end
|
|
|
|
def create_job(name, status)
|
|
pipeline = create(:ci_pipeline, project: project)
|
|
create(:ci_build, :tags, :triggered, :artifacts,
|
|
pipeline: pipeline, name: name, status: status)
|
|
end
|
|
end
|
|
|
|
def get_index(**extra_params)
|
|
params = {
|
|
namespace_id: project.namespace.to_param,
|
|
project_id: project
|
|
}
|
|
|
|
get :index, params.merge(extra_params)
|
|
end
|
|
end
|
|
|
|
describe 'GET show' do
|
|
let!(:job) { create(:ci_build, :failed, pipeline: pipeline) }
|
|
|
|
context 'when requesting HTML' do
|
|
context 'when job exists' do
|
|
before do
|
|
get_show(id: job.id)
|
|
end
|
|
|
|
it 'has a job' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(assigns(:build).id).to eq(job.id)
|
|
end
|
|
end
|
|
|
|
context 'when job does not exist' do
|
|
before do
|
|
get_show(id: 1234)
|
|
end
|
|
|
|
it 'renders not_found' do
|
|
expect(response).to have_http_status(:not_found)
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when requesting JSON' do
|
|
let(:merge_request) { create(:merge_request, source_project: project) }
|
|
|
|
before do
|
|
project.add_developer(user)
|
|
sign_in(user)
|
|
|
|
allow_any_instance_of(Ci::Build).to receive(:merge_request).and_return(merge_request)
|
|
|
|
get_show(id: job.id, format: :json)
|
|
end
|
|
|
|
it 'exposes needed information' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json_response['raw_path']).to match(/jobs\/\d+\/raw\z/)
|
|
expect(json_response.dig('merge_request', 'path')).to match(/merge_requests\/\d+\z/)
|
|
expect(json_response['new_issue_path'])
|
|
.to include('/issues/new')
|
|
end
|
|
end
|
|
|
|
def get_show(**extra_params)
|
|
params = {
|
|
namespace_id: project.namespace.to_param,
|
|
project_id: project
|
|
}
|
|
|
|
get :show, params.merge(extra_params)
|
|
end
|
|
end
|
|
|
|
describe 'GET trace.json' do
|
|
before do
|
|
get_trace
|
|
end
|
|
|
|
context 'when job has a trace' do
|
|
let(:job) { create(:ci_build, :trace, pipeline: pipeline) }
|
|
|
|
it 'returns a trace' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json_response['id']).to eq job.id
|
|
expect(json_response['status']).to eq job.status
|
|
expect(json_response['html']).to eq('BUILD TRACE')
|
|
end
|
|
end
|
|
|
|
context 'when job has no traces' do
|
|
let(:job) { create(:ci_build, pipeline: pipeline) }
|
|
|
|
it 'returns no traces' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json_response['id']).to eq job.id
|
|
expect(json_response['status']).to eq job.status
|
|
expect(json_response['html']).to be_nil
|
|
end
|
|
end
|
|
|
|
context 'when job has a trace with ANSI sequence and Unicode' do
|
|
let(:job) { create(:ci_build, :unicode_trace, pipeline: pipeline) }
|
|
|
|
it 'returns a trace with Unicode' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json_response['id']).to eq job.id
|
|
expect(json_response['status']).to eq job.status
|
|
expect(json_response['html']).to include("ヾ(´༎ຶД༎ຶ`)ノ")
|
|
end
|
|
end
|
|
|
|
def get_trace
|
|
get :trace, namespace_id: project.namespace,
|
|
project_id: project,
|
|
id: job.id,
|
|
format: :json
|
|
end
|
|
end
|
|
|
|
describe 'GET status.json' do
|
|
let(:job) { create(:ci_build, pipeline: pipeline) }
|
|
let(:status) { job.detailed_status(double('user')) }
|
|
|
|
before do
|
|
get :status, namespace_id: project.namespace,
|
|
project_id: project,
|
|
id: job.id,
|
|
format: :json
|
|
end
|
|
|
|
it 'return a detailed job status in json' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(json_response['text']).to eq status.text
|
|
expect(json_response['label']).to eq status.label
|
|
expect(json_response['icon']).to eq status.icon
|
|
expect(json_response['favicon']).to eq "/assets/ci_favicons/#{status.favicon}.ico"
|
|
end
|
|
end
|
|
|
|
describe 'POST retry' do
|
|
before do
|
|
project.add_developer(user)
|
|
sign_in(user)
|
|
|
|
post_retry
|
|
end
|
|
|
|
context 'when job is retryable' do
|
|
let(:job) { create(:ci_build, :retryable, pipeline: pipeline) }
|
|
|
|
it 'redirects to the retried job page' do
|
|
expect(response).to have_http_status(:found)
|
|
expect(response).to redirect_to(namespace_project_job_path(id: Ci::Build.last.id))
|
|
end
|
|
end
|
|
|
|
context 'when job is not retryable' do
|
|
let(:job) { create(:ci_build, pipeline: pipeline) }
|
|
|
|
it 'renders unprocessable_entity' do
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
def post_retry
|
|
post :retry, namespace_id: project.namespace,
|
|
project_id: project,
|
|
id: job.id
|
|
end
|
|
end
|
|
|
|
describe 'POST play' do
|
|
before do
|
|
project.add_developer(user)
|
|
|
|
create(:protected_branch, :developers_can_merge,
|
|
name: 'master', project: project)
|
|
|
|
sign_in(user)
|
|
|
|
post_play
|
|
end
|
|
|
|
context 'when job is playable' do
|
|
let(:job) { create(:ci_build, :playable, pipeline: pipeline) }
|
|
|
|
it 'redirects to the played job page' do
|
|
expect(response).to have_http_status(:found)
|
|
expect(response).to redirect_to(namespace_project_job_path(id: job.id))
|
|
end
|
|
|
|
it 'transits to pending' do
|
|
expect(job.reload).to be_pending
|
|
end
|
|
end
|
|
|
|
context 'when job is not playable' do
|
|
let(:job) { create(:ci_build, pipeline: pipeline) }
|
|
|
|
it 'renders unprocessable_entity' do
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
def post_play
|
|
post :play, namespace_id: project.namespace,
|
|
project_id: project,
|
|
id: job.id
|
|
end
|
|
end
|
|
|
|
describe 'POST cancel' do
|
|
before do
|
|
project.add_developer(user)
|
|
sign_in(user)
|
|
|
|
post_cancel
|
|
end
|
|
|
|
context 'when job is cancelable' do
|
|
let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
|
|
|
|
it 'redirects to the canceled job page' do
|
|
expect(response).to have_http_status(:found)
|
|
expect(response).to redirect_to(namespace_project_job_path(id: job.id))
|
|
end
|
|
|
|
it 'transits to canceled' do
|
|
expect(job.reload).to be_canceled
|
|
end
|
|
end
|
|
|
|
context 'when job is not cancelable' do
|
|
let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
|
|
|
|
it 'returns unprocessable_entity' do
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
def post_cancel
|
|
post :cancel, namespace_id: project.namespace,
|
|
project_id: project,
|
|
id: job.id
|
|
end
|
|
end
|
|
|
|
describe 'POST cancel_all' do
|
|
before do
|
|
project.add_developer(user)
|
|
sign_in(user)
|
|
end
|
|
|
|
context 'when jobs are cancelable' do
|
|
before do
|
|
create_list(:ci_build, 2, :cancelable, pipeline: pipeline)
|
|
|
|
post_cancel_all
|
|
end
|
|
|
|
it 'redirects to a index page' do
|
|
expect(response).to have_http_status(:found)
|
|
expect(response).to redirect_to(namespace_project_jobs_path)
|
|
end
|
|
|
|
it 'transits to canceled' do
|
|
expect(Ci::Build.all).to all(be_canceled)
|
|
end
|
|
end
|
|
|
|
context 'when jobs are not cancelable' do
|
|
before do
|
|
create_list(:ci_build, 2, :canceled, pipeline: pipeline)
|
|
|
|
post_cancel_all
|
|
end
|
|
|
|
it 'redirects to a index page' do
|
|
expect(response).to have_http_status(:found)
|
|
expect(response).to redirect_to(namespace_project_jobs_path)
|
|
end
|
|
end
|
|
|
|
def post_cancel_all
|
|
post :cancel_all, namespace_id: project.namespace,
|
|
project_id: project
|
|
end
|
|
end
|
|
|
|
describe 'POST erase' do
|
|
before do
|
|
project.add_developer(user)
|
|
sign_in(user)
|
|
|
|
post_erase
|
|
end
|
|
|
|
context 'when job is erasable' do
|
|
let(:job) { create(:ci_build, :erasable, :trace, pipeline: pipeline) }
|
|
|
|
it 'redirects to the erased job page' do
|
|
expect(response).to have_http_status(:found)
|
|
expect(response).to redirect_to(namespace_project_job_path(id: job.id))
|
|
end
|
|
|
|
it 'erases artifacts' do
|
|
expect(job.artifacts_file.exists?).to be_falsey
|
|
expect(job.artifacts_metadata.exists?).to be_falsey
|
|
end
|
|
|
|
it 'erases trace' do
|
|
expect(job.trace.exist?).to be_falsey
|
|
end
|
|
end
|
|
|
|
context 'when job is not erasable' do
|
|
let(:job) { create(:ci_build, :erased, pipeline: pipeline) }
|
|
|
|
it 'returns unprocessable_entity' do
|
|
expect(response).to have_http_status(:unprocessable_entity)
|
|
end
|
|
end
|
|
|
|
def post_erase
|
|
post :erase, namespace_id: project.namespace,
|
|
project_id: project,
|
|
id: job.id
|
|
end
|
|
end
|
|
|
|
describe 'GET raw' do
|
|
before do
|
|
get_raw
|
|
end
|
|
|
|
context 'when job has a trace file' do
|
|
let(:job) { create(:ci_build, :trace, pipeline: pipeline) }
|
|
|
|
it 'send a trace file' do
|
|
expect(response).to have_http_status(:ok)
|
|
expect(response.content_type).to eq 'text/plain; charset=utf-8'
|
|
expect(response.body).to eq 'BUILD TRACE'
|
|
end
|
|
end
|
|
|
|
context 'when job does not have a trace file' do
|
|
let(:job) { create(:ci_build, pipeline: pipeline) }
|
|
|
|
it 'returns not_found' do
|
|
expect(response).to have_http_status(:not_found)
|
|
end
|
|
end
|
|
|
|
def get_raw
|
|
post :raw, namespace_id: project.namespace,
|
|
project_id: project,
|
|
id: job.id
|
|
end
|
|
end
|
|
end
|