diff options
Diffstat (limited to 'spec/requests/api/jobs_spec.rb')
-rw-r--r-- | spec/requests/api/jobs_spec.rb | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb index bd8aeb65d3f..18b5c00d64f 100644 --- a/spec/requests/api/jobs_spec.rb +++ b/spec/requests/api/jobs_spec.rb @@ -271,6 +271,178 @@ describe API::Jobs do end end + describe 'GET /projects/:id/pipelines/:pipeline_id/bridges' do + let!(:bridge) { create(:ci_bridge, pipeline: pipeline) } + let(:downstream_pipeline) { create(:ci_pipeline) } + + let!(:pipeline_source) do + create(:ci_sources_pipeline, + source_pipeline: pipeline, + source_project: project, + source_job: bridge, + pipeline: downstream_pipeline, + project: downstream_pipeline.project) + end + + let(:query) { Hash.new } + + before do |example| + unless example.metadata[:skip_before_request] + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query + end + end + + context 'authorized user' do + it 'returns pipeline bridges' do + expect(response).to have_gitlab_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + end + + it 'returns correct values' do + expect(json_response).not_to be_empty + expect(json_response.first['commit']['id']).to eq project.commit.id + expect(json_response.first['id']).to eq bridge.id + expect(json_response.first['name']).to eq bridge.name + expect(json_response.first['stage']).to eq bridge.stage + end + + it 'returns pipeline data' do + json_bridge = json_response.first + + expect(json_bridge['pipeline']).not_to be_empty + expect(json_bridge['pipeline']['id']).to eq bridge.pipeline.id + expect(json_bridge['pipeline']['ref']).to eq bridge.pipeline.ref + expect(json_bridge['pipeline']['sha']).to eq bridge.pipeline.sha + expect(json_bridge['pipeline']['status']).to eq bridge.pipeline.status + end + + it 'returns downstream pipeline data' do + json_bridge = json_response.first + + expect(json_bridge['downstream_pipeline']).not_to be_empty + expect(json_bridge['downstream_pipeline']['id']).to eq downstream_pipeline.id + expect(json_bridge['downstream_pipeline']['ref']).to eq downstream_pipeline.ref + expect(json_bridge['downstream_pipeline']['sha']).to eq downstream_pipeline.sha + expect(json_bridge['downstream_pipeline']['status']).to eq downstream_pipeline.status + end + + context 'filter bridges' do + before do + create_bridge(pipeline, :pending) + create_bridge(pipeline, :running) + end + + context 'with one scope element' do + let(:query) { { 'scope' => 'pending' } } + + it :skip_before_request do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to be_an Array + expect(json_response.count).to eq 1 + expect(json_response.first["status"]).to eq "pending" + end + end + + context 'with array of scope elements' do + let(:query) { { scope: %w(pending running) } } + + it :skip_before_request do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to be_an Array + expect(json_response.count).to eq 2 + json_response.each { |r| expect(%w(pending running).include?(r['status'])).to be true } + end + end + end + + context 'respond 400 when scope contains invalid state' do + let(:query) { { scope: %w(unknown running) } } + + it { expect(response).to have_gitlab_http_status(:bad_request) } + end + + context 'bridges in different pipelines' do + let!(:pipeline2) { create(:ci_empty_pipeline, project: project) } + let!(:bridge2) { create(:ci_bridge, pipeline: pipeline2) } + + it 'excludes bridges from other pipelines' do + json_response.each { |bridge| expect(bridge['pipeline']['id']).to eq(pipeline.id) } + end + end + + it 'avoids N+1 queries' do + control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query + end.count + + 3.times { create_bridge(pipeline) } + + expect do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query + end.not_to exceed_all_query_limit(control_count) + end + end + + context 'unauthorized user' do + context 'when user is not logged in' do + let(:api_user) { nil } + + it 'does not return bridges' do + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + + context 'when user is guest' do + let(:api_user) { guest } + + it 'does not return bridges' do + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context 'when user has no read access for pipeline' do + before do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(api_user, :read_pipeline, pipeline).and_return(false) + end + + it 'does not return bridges' do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user) + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context 'when user has no read_build access for project' do + before do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(api_user, :read_build, project).and_return(false) + end + + it 'does not return bridges' do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user) + expect(response).to have_gitlab_http_status(:forbidden) + end + end + end + + def create_bridge(pipeline, status = :created) + create(:ci_bridge, status: status, pipeline: pipeline).tap do |bridge| + downstream_pipeline = create(:ci_pipeline) + create(:ci_sources_pipeline, + source_pipeline: pipeline, + source_project: pipeline.project, + source_job: bridge, + pipeline: downstream_pipeline, + project: downstream_pipeline.project) + end + end + end + describe 'GET /projects/:id/jobs/:job_id' do before do |example| unless example.metadata[:skip_before_request] |