Merge branch '42568-pipeline-empty-state' into 'master'

Resolve "Wrong empty state for cancelled build, hides existing logs!"

Closes #42568

See merge request gitlab-org/gitlab-ce!17646
This commit is contained in:
Kamil Trzciński 2018-04-06 22:32:44 +00:00
commit 9421a597b7
32 changed files with 513 additions and 58 deletions

View File

@ -1,7 +1,7 @@
- illustration = local_assigns.fetch(:illustration) - illustration = local_assigns.fetch(:illustration)
- illustration_size = local_assigns.fetch(:illustration_size) - illustration_size = local_assigns.fetch(:illustration_size)
- title = local_assigns.fetch(:title) - title = local_assigns.fetch(:title)
- content = local_assigns.fetch(:content) - content = local_assigns.fetch(:content, nil)
- action = local_assigns.fetch(:action, nil) - action = local_assigns.fetch(:action, nil)
.row.empty-state .row.empty-state
@ -11,7 +11,8 @@
.col-xs-12 .col-xs-12
.text-content .text-content
%h4.text-center= title %h4.text-center= title
%p= content - if content
%p= content
- if action - if action
.text-center .text-center
= action = action

View File

@ -0,0 +1,9 @@
- detailed_status = @build.detailed_status(current_user)
- illustration = detailed_status.illustration
= render 'empty_state',
illustration: illustration[:image],
illustration_size: illustration[:size],
title: illustration[:title],
content: illustration[:content],
action: detailed_status.has_action? ? link_to(detailed_status.action_button_title, detailed_status.action_path, method: detailed_status.action_method, class: 'btn btn-primary', title: detailed_status.action_button_title) : nil

View File

@ -54,7 +54,8 @@
Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)} Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)}
- else - else
Job has been erased #{time_ago_with_tooltip(@build.erased_at)} Job has been erased #{time_ago_with_tooltip(@build.erased_at)}
- if @build.started?
- if @build.has_trace?
.build-trace-container.prepend-top-default .build-trace-container.prepend-top-default
.top-bar.js-top-bar .top-bar.js-top-bar
.js-truncated-info.truncated-info.hidden-xs.pull-left.hidden< .js-truncated-info.truncated-info.hidden-xs.pull-left.hidden<
@ -88,25 +89,9 @@
%pre.build-trace#build-trace %pre.build-trace#build-trace
%code.bash.js-build-output %code.bash.js-build-output
.build-loader-animation.js-build-refresh .build-loader-animation.js-build-refresh
- elsif @build.playable?
= render 'empty_state',
illustration: 'illustrations/manual_action.svg',
illustration_size: 'svg-394',
title: _('This job requires a manual action'),
content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'),
action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), method: :post, class: 'btn btn-primary', title: _('Trigger this manual action') )
- elsif @build.created?
= render 'empty_state',
illustration: 'illustrations/job_not_triggered.svg',
illustration_size: 'svg-306',
title: _('This job has not been triggered yet'),
content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered')
- else - else
= render 'empty_state', = render "empty_states"
illustration: 'illustrations/pending_job_empty.svg',
illustration_size: 'svg-430',
title: _('This job has not started yet'),
content: _('This job is in pending state and is waiting to be picked by a runner')
= render "sidebar", builds: @builds = render "sidebar", builds: @builds
.js-build-options{ data: javascript_build_options } .js-build-options{ data: javascript_build_options }

View File

@ -0,0 +1,5 @@
---
title: Improve empty state for canceled job
merge_request: 17646
author:
type: fixed

View File

@ -11,7 +11,7 @@ module SharedBuilds
step 'project has a recent build' do step 'project has a recent build' do
@pipeline = create(:ci_empty_pipeline, project: @project, sha: @project.commit.sha, ref: 'master') @pipeline = create(:ci_empty_pipeline, project: @project, sha: @project.commit.sha, ref: 'master')
@build = create(:ci_build, :running, :coverage, pipeline: @pipeline) @build = create(:ci_build, :running, :coverage, :trace_artifact, pipeline: @pipeline)
end end
step 'recent build is successful' do step 'recent build is successful' do

View File

@ -23,6 +23,10 @@ module Gitlab
'Cancel' 'Cancel'
end end
def action_button_title
_('Cancel this job')
end
def self.matches?(build, user) def self.matches?(build, user)
build.cancelable? build.cancelable?
end end

View File

@ -0,0 +1,21 @@
module Gitlab
module Ci
module Status
module Build
class Canceled < Status::Extended
def illustration
{
image: 'illustrations/canceled-job_empty.svg',
size: 'svg-430',
title: _('This job has been canceled')
}
end
def self.matches?(build, user)
build.canceled?
end
end
end
end
end
end

View File

@ -0,0 +1,22 @@
module Gitlab
module Ci
module Status
module Build
class Created < Status::Extended
def illustration
{
image: 'illustrations/job_not_triggered.svg',
size: 'svg-306',
title: _('This job has not been triggered yet'),
content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered')
}
end
def self.matches?(build, user)
build.created?
end
end
end
end
end
end

View File

@ -0,0 +1,21 @@
module Gitlab
module Ci
module Status
module Build
class Erased < Status::Extended
def illustration
{
image: 'illustrations/skipped-job_empty.svg',
size: 'svg-430',
title: _('Job has been erased')
}
end
def self.matches?(build, user)
build.erased?
end
end
end
end
end
end

View File

@ -4,7 +4,13 @@ module Gitlab
module Build module Build
class Factory < Status::Factory class Factory < Status::Factory
def self.extended_statuses def self.extended_statuses
[[Status::Build::Cancelable, [[Status::Build::Erased,
Status::Build::Manual,
Status::Build::Canceled,
Status::Build::Created,
Status::Build::Pending,
Status::Build::Skipped],
[Status::Build::Cancelable,
Status::Build::Retryable], Status::Build::Retryable],
[Status::Build::Failed], [Status::Build::Failed],
[Status::Build::FailedAllowed, [Status::Build::FailedAllowed,

View File

@ -0,0 +1,22 @@
module Gitlab
module Ci
module Status
module Build
class Manual < Status::Extended
def illustration
{
image: 'illustrations/manual_action.svg',
size: 'svg-394',
title: _('This job requires a manual action'),
content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments')
}
end
def self.matches?(build, user)
build.playable?
end
end
end
end
end
end

View File

@ -0,0 +1,22 @@
module Gitlab
module Ci
module Status
module Build
class Pending < Status::Extended
def illustration
{
image: 'illustrations/pending_job_empty.svg',
size: 'svg-430',
title: _('This job has not started yet'),
content: _('This job is in pending state and is waiting to be picked by a runner')
}
end
def self.matches?(build, user)
build.pending?
end
end
end
end
end
end

View File

@ -19,6 +19,10 @@ module Gitlab
'Play' 'Play'
end end
def action_button_title
_('Trigger this manual action')
end
def action_path def action_path
play_project_job_path(subject.project, subject) play_project_job_path(subject.project, subject)
end end

View File

@ -15,6 +15,10 @@ module Gitlab
'Retry' 'Retry'
end end
def action_button_title
_('Retry this job')
end
def action_path def action_path
retry_project_job_path(subject.project, subject) retry_project_job_path(subject.project, subject)
end end

View File

@ -0,0 +1,21 @@
module Gitlab
module Ci
module Status
module Build
class Skipped < Status::Extended
def illustration
{
image: 'illustrations/skipped-job_empty.svg',
size: 'svg-430',
title: _('This job has been skipped')
}
end
def self.matches?(build, user)
build.skipped?
end
end
end
end
end
end

View File

@ -19,6 +19,10 @@ module Gitlab
'Stop' 'Stop'
end end
def action_button_title
_('Stop this environment')
end
def action_path def action_path
play_project_job_path(subject.project, subject) play_project_job_path(subject.project, subject)
end end

View File

@ -22,6 +22,10 @@ module Gitlab
raise NotImplementedError raise NotImplementedError
end end
def illustration
raise NotImplementedError
end
def label def label
raise NotImplementedError raise NotImplementedError
end end
@ -58,6 +62,10 @@ module Gitlab
raise NotImplementedError raise NotImplementedError
end end
def action_button_title
raise NotImplementedError
end
# Hint that appears on all the pipeline graph tooltips and builds on the right sidebar in Job detail view # Hint that appears on all the pipeline graph tooltips and builds on the right sidebar in Job detail view
def status_tooltip def status_tooltip
label label

View File

@ -9,6 +9,7 @@ describe 'Merge request < User sees mini pipeline graph', :js do
before do before do
build.run build.run
build.trace.set('hello')
sign_in(user) sign_in(user)
visit_merge_request visit_merge_request
end end
@ -26,15 +27,15 @@ describe 'Merge request < User sees mini pipeline graph', :js do
let(:artifacts_file2) { fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'), 'image/png') } let(:artifacts_file2) { fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'), 'image/png') }
before do before do
create(:ci_build, pipeline: pipeline, legacy_artifacts_file: artifacts_file1) create(:ci_build, :success, :trace_artifact, pipeline: pipeline, legacy_artifacts_file: artifacts_file1)
create(:ci_build, pipeline: pipeline, when: 'manual') create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
end end
it 'avoids repeated database queries' do it 'avoids repeated database queries' do
before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') } before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
create(:ci_build, pipeline: pipeline, legacy_artifacts_file: artifacts_file2) create(:ci_build, :success, :trace_artifact, pipeline: pipeline, legacy_artifacts_file: artifacts_file2)
create(:ci_build, pipeline: pipeline, when: 'manual') create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') } after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }

View File

@ -1,16 +1,15 @@
require 'spec_helper' require 'spec_helper'
describe 'User browses a job', :js do describe 'User browses a job', :js do
let!(:build) { create(:ci_build, :running, :coverage, pipeline: pipeline) }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:user_access_level) { :developer }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
let!(:build) { create(:ci_build, :success, :trace_artifact, :coverage, pipeline: pipeline) }
before do before do
project.add_master(user) project.add_master(user)
project.enable_ci project.enable_ci
build.success
build.trace.set('job trace')
sign_in(user) sign_in(user)
@ -21,7 +20,9 @@ describe 'User browses a job', :js do
expect(page).to have_content("Job ##{build.id}") expect(page).to have_content("Job ##{build.id}")
expect(page).to have_css('#build-trace') expect(page).to have_css('#build-trace')
accept_confirm { click_link('Erase') } # scroll to the top of the page first
execute_script "window.scrollTo(0,0)"
accept_confirm { find('.js-erase-link').click }
expect(page).to have_no_css('.artifacts') expect(page).to have_no_css('.artifacts')
expect(build).not_to have_trace expect(build).not_to have_trace
@ -36,7 +37,7 @@ describe 'User browses a job', :js do
end end
context 'with a failed job' do context 'with a failed job' do
let!(:build) { create(:ci_build, :failed, pipeline: pipeline) } let!(:build) { create(:ci_build, :failed, :trace_artifact, pipeline: pipeline) }
it 'displays the failure reason' do it 'displays the failure reason' do
within('.builds-container') do within('.builds-container') do
@ -47,7 +48,7 @@ describe 'User browses a job', :js do
end end
context 'when a failed job has been retried' do context 'when a failed job has been retried' do
let!(:build) { create(:ci_build, :failed, :retried, pipeline: pipeline) } let!(:build) { create(:ci_build, :failed, :retried, :trace_artifact, pipeline: pipeline) }
it 'displays the failure reason and retried label' do it 'displays the failure reason and retried label' do
within('.builds-container') do within('.builds-container') do

View File

@ -113,7 +113,7 @@ feature 'Jobs' do
describe "GET /:project/jobs/:id" do describe "GET /:project/jobs/:id" do
context "Job from project" do context "Job from project" do
let(:job) { create(:ci_build, :success, pipeline: pipeline) } let(:job) { create(:ci_build, :success, :trace_live, pipeline: pipeline) }
before do before do
visit project_job_path(project, job) visit project_job_path(project, job)
@ -136,7 +136,7 @@ feature 'Jobs' do
end end
context 'when job is not running', :js do context 'when job is not running', :js do
let(:job) { create(:ci_build, :success, pipeline: pipeline) } let(:job) { create(:ci_build, :success, :trace_artifact, pipeline: pipeline) }
before do before do
visit project_job_path(project, job) visit project_job_path(project, job)
@ -153,7 +153,7 @@ feature 'Jobs' do
end end
context 'if job failed' do context 'if job failed' do
let(:job) { create(:ci_build, :failed, pipeline: pipeline) } let(:job) { create(:ci_build, :failed, :trace_artifact, pipeline: pipeline) }
before do before do
visit project_job_path(project, job) visit project_job_path(project, job)
@ -339,7 +339,7 @@ feature 'Jobs' do
context 'job is successfull and has deployment' do context 'job is successfull and has deployment' do
let(:deployment) { create(:deployment) } let(:deployment) { create(:deployment) }
let(:job) { create(:ci_build, :success, environment: environment.name, deployments: [deployment], pipeline: pipeline) } let(:job) { create(:ci_build, :success, :trace_artifact, environment: environment.name, deployments: [deployment], pipeline: pipeline) }
it 'shows a link for the job' do it 'shows a link for the job' do
visit project_job_path(project, job) visit project_job_path(project, job)
@ -349,7 +349,7 @@ feature 'Jobs' do
end end
context 'job is complete and not successful' do context 'job is complete and not successful' do
let(:job) { create(:ci_build, :failed, environment: environment.name, pipeline: pipeline) } let(:job) { create(:ci_build, :failed, :trace_artifact, environment: environment.name, pipeline: pipeline) }
it 'shows a link for the job' do it 'shows a link for the job' do
visit project_job_path(project, job) visit project_job_path(project, job)
@ -360,7 +360,7 @@ feature 'Jobs' do
context 'job creates a new deployment' do context 'job creates a new deployment' do
let!(:deployment) { create(:deployment, environment: environment, sha: project.commit.id) } let!(:deployment) { create(:deployment, environment: environment, sha: project.commit.id) }
let(:job) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) } let(:job) { create(:ci_build, :success, :trace_artifact, environment: environment.name, pipeline: pipeline) }
it 'shows a link to latest deployment' do it 'shows a link to latest deployment' do
visit project_job_path(project, job) visit project_job_path(project, job)
@ -379,6 +379,7 @@ feature 'Jobs' do
end end
it 'shows manual action empty state' do it 'shows manual action empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).to have_content('This job requires a manual action') expect(page).to have_content('This job requires a manual action')
expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments') expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments')
expect(page).to have_link('Trigger this manual action') expect(page).to have_link('Trigger this manual action')
@ -402,6 +403,7 @@ feature 'Jobs' do
end end
it 'shows empty state' do it 'shows empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).to have_content('This job has not been triggered yet') expect(page).to have_content('This job has not been triggered yet')
expect(page).to have_content('This job depends on upstream jobs that need to succeed in order for this job to be triggered') expect(page).to have_content('This job depends on upstream jobs that need to succeed in order for this job to be triggered')
end end
@ -415,10 +417,53 @@ feature 'Jobs' do
end end
it 'shows pending empty state' do it 'shows pending empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).to have_content('This job has not started yet') expect(page).to have_content('This job has not started yet')
expect(page).to have_content('This job is in pending state and is waiting to be picked by a runner') expect(page).to have_content('This job is in pending state and is waiting to be picked by a runner')
end end
end end
context 'Canceled job' do
context 'with log' do
let(:job) { create(:ci_build, :canceled, :trace_artifact, pipeline: pipeline) }
before do
visit project_job_path(project, job)
end
it 'renders job log' do
expect(page).to have_selector('.js-build-output')
end
end
context 'without log' do
let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
before do
visit project_job_path(project, job)
end
it 'renders empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).not_to have_selector('.js-build-output')
expect(page).to have_content('This job has been canceled')
end
end
end
context 'Skipped job' do
let(:job) { create(:ci_build, :skipped, pipeline: pipeline) }
before do
visit project_job_path(project, job)
end
it 'renders empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).not_to have_selector('.js-build-output')
expect(page).to have_content('This job has been skipped')
end
end
end end
describe "POST /:project/jobs/:id/cancel", :js do describe "POST /:project/jobs/:id/cancel", :js do

View File

@ -90,6 +90,10 @@ describe Gitlab::Ci::Status::Build::Cancelable do
describe '#action_title' do describe '#action_title' do
it { expect(subject.action_title).to eq 'Cancel' } it { expect(subject.action_title).to eq 'Cancel' }
end end
describe '#action_button_title' do
it { expect(subject.action_button_title).to eq 'Cancel this job' }
end
end end
describe '.matches?' do describe '.matches?' do

View File

@ -0,0 +1,33 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Build::Canceled do
let(:user) { create(:user) }
subject do
described_class.new(double('subject'))
end
describe '#illustration' do
it { expect(subject.illustration).to include(:image, :size, :title) }
end
describe '.matches?' do
subject {described_class.matches?(build, user) }
context 'when build is canceled' do
let(:build) { create(:ci_build, :canceled) }
it 'is a correct match' do
expect(subject).to be true
end
end
context 'when build is not canceled' do
let(:build) { create(:ci_build) }
it 'does not match' do
expect(subject).to be false
end
end
end
end

View File

@ -0,0 +1,33 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Build::Created do
let(:user) { create(:user) }
subject do
described_class.new(double('subject'))
end
describe '#illustration' do
it { expect(subject.illustration).to include(:image, :size, :title, :content) }
end
describe '.matches?' do
subject {described_class.matches?(build, user) }
context 'when build is created' do
let(:build) { create(:ci_build, :created) }
it 'is a correct match' do
expect(subject).to be true
end
end
context 'when build is not created' do
let(:build) { create(:ci_build) }
it 'does not match' do
expect(subject).to be false
end
end
end
end

View File

@ -0,0 +1,33 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Build::Erased do
let(:user) { create(:user) }
subject do
described_class.new(double('subject'))
end
describe '#illustration' do
it { expect(subject.illustration).to include(:image, :size, :title) }
end
describe '.matches?' do
subject { described_class.matches?(build, user) }
context 'when build is erased' do
let(:build) { create(:ci_build, :success, :erased) }
it 'is a correct match' do
expect(subject).to be true
end
end
context 'when build is not erased' do
let(:build) { create(:ci_build, :success, :trace_artifact) }
it 'does not match' do
expect(subject).to be false
end
end
end
end

View File

@ -13,7 +13,7 @@ describe Gitlab::Ci::Status::Build::Factory do
end end
context 'when build is successful' do context 'when build is successful' do
let(:build) { create(:ci_build, :success) } let(:build) { create(:ci_build, :success, :trace_artifact) }
it 'matches correct core status' do it 'matches correct core status' do
expect(factory.core_status).to be_a Gitlab::Ci::Status::Success expect(factory.core_status).to be_a Gitlab::Ci::Status::Success
@ -38,6 +38,33 @@ describe Gitlab::Ci::Status::Build::Factory do
end end
end end
context 'when build is erased' do
let(:build) { create(:ci_build, :success, :erased) }
it 'matches correct core status' do
expect(factory.core_status).to be_a Gitlab::Ci::Status::Success
end
it 'matches correct extended statuses' do
expect(factory.extended_statuses)
.to eq [Gitlab::Ci::Status::Build::Erased,
Gitlab::Ci::Status::Build::Retryable]
end
it 'fabricates a retryable build status' do
expect(status).to be_a Gitlab::Ci::Status::Build::Retryable
end
it 'fabricates status with correct details' do
expect(status.text).to eq 'passed'
expect(status.icon).to eq 'status_success'
expect(status.favicon).to eq 'favicon_status_success'
expect(status.label).to eq 'passed'
expect(status).to have_details
expect(status).to have_action
end
end
context 'when build is failed' do context 'when build is failed' do
context 'when build is not allowed to fail' do context 'when build is not allowed to fail' do
let(:build) { create(:ci_build, :failed) } let(:build) { create(:ci_build, :failed) }
@ -106,7 +133,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'matches correct extended statuses' do it 'matches correct extended statuses' do
expect(factory.extended_statuses) expect(factory.extended_statuses)
.to eq [Gitlab::Ci::Status::Build::Retryable] .to eq [Gitlab::Ci::Status::Build::Canceled, Gitlab::Ci::Status::Build::Retryable]
end end
it 'fabricates a retryable build status' do it 'fabricates a retryable build status' do
@ -117,6 +144,7 @@ describe Gitlab::Ci::Status::Build::Factory do
expect(status.text).to eq 'canceled' expect(status.text).to eq 'canceled'
expect(status.icon).to eq 'status_canceled' expect(status.icon).to eq 'status_canceled'
expect(status.favicon).to eq 'favicon_status_canceled' expect(status.favicon).to eq 'favicon_status_canceled'
expect(status.illustration).to include(:image, :size, :title)
expect(status.label).to eq 'canceled' expect(status.label).to eq 'canceled'
expect(status).to have_details expect(status).to have_details
expect(status).to have_action expect(status).to have_action
@ -158,7 +186,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'matches correct extended statuses' do it 'matches correct extended statuses' do
expect(factory.extended_statuses) expect(factory.extended_statuses)
.to eq [Gitlab::Ci::Status::Build::Cancelable] .to eq [Gitlab::Ci::Status::Build::Pending, Gitlab::Ci::Status::Build::Cancelable]
end end
it 'fabricates a cancelable build status' do it 'fabricates a cancelable build status' do
@ -169,6 +197,7 @@ describe Gitlab::Ci::Status::Build::Factory do
expect(status.text).to eq 'pending' expect(status.text).to eq 'pending'
expect(status.icon).to eq 'status_pending' expect(status.icon).to eq 'status_pending'
expect(status.favicon).to eq 'favicon_status_pending' expect(status.favicon).to eq 'favicon_status_pending'
expect(status.illustration).to include(:image, :size, :title, :content)
expect(status.label).to eq 'pending' expect(status.label).to eq 'pending'
expect(status).to have_details expect(status).to have_details
expect(status).to have_action expect(status).to have_action
@ -182,18 +211,19 @@ describe Gitlab::Ci::Status::Build::Factory do
expect(factory.core_status).to be_a Gitlab::Ci::Status::Skipped expect(factory.core_status).to be_a Gitlab::Ci::Status::Skipped
end end
it 'does not match extended statuses' do it 'matches correct extended statuses' do
expect(factory.extended_statuses).to be_empty expect(factory.extended_statuses).to eq [Gitlab::Ci::Status::Build::Skipped]
end end
it 'fabricates a core skipped status' do it 'fabricates a skipped build status' do
expect(status).to be_a Gitlab::Ci::Status::Skipped expect(status).to be_a Gitlab::Ci::Status::Build::Skipped
end end
it 'fabricates status with correct details' do it 'fabricates status with correct details' do
expect(status.text).to eq 'skipped' expect(status.text).to eq 'skipped'
expect(status.icon).to eq 'status_skipped' expect(status.icon).to eq 'status_skipped'
expect(status.favicon).to eq 'favicon_status_skipped' expect(status.favicon).to eq 'favicon_status_skipped'
expect(status.illustration).to include(:image, :size, :title)
expect(status.label).to eq 'skipped' expect(status.label).to eq 'skipped'
expect(status).to have_details expect(status).to have_details
expect(status).not_to have_action expect(status).not_to have_action
@ -210,7 +240,8 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'matches correct extended statuses' do it 'matches correct extended statuses' do
expect(factory.extended_statuses) expect(factory.extended_statuses)
.to eq [Gitlab::Ci::Status::Build::Play, .to eq [Gitlab::Ci::Status::Build::Manual,
Gitlab::Ci::Status::Build::Play,
Gitlab::Ci::Status::Build::Action] Gitlab::Ci::Status::Build::Action]
end end
@ -223,6 +254,7 @@ describe Gitlab::Ci::Status::Build::Factory do
expect(status.group).to eq 'manual' expect(status.group).to eq 'manual'
expect(status.icon).to eq 'status_manual' expect(status.icon).to eq 'status_manual'
expect(status.favicon).to eq 'favicon_status_manual' expect(status.favicon).to eq 'favicon_status_manual'
expect(status.illustration).to include(:image, :size, :title, :content)
expect(status.label).to include 'manual play action' expect(status.label).to include 'manual play action'
expect(status).to have_details expect(status).to have_details
expect(status.action_path).to include 'play' expect(status.action_path).to include 'play'
@ -257,7 +289,8 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'matches correct extended statuses' do it 'matches correct extended statuses' do
expect(factory.extended_statuses) expect(factory.extended_statuses)
.to eq [Gitlab::Ci::Status::Build::Stop, .to eq [Gitlab::Ci::Status::Build::Manual,
Gitlab::Ci::Status::Build::Stop,
Gitlab::Ci::Status::Build::Action] Gitlab::Ci::Status::Build::Action]
end end

View File

@ -0,0 +1,34 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Build::Manual do
let(:user) { create(:user) }
subject do
build = create(:ci_build, :manual)
described_class.new(Gitlab::Ci::Status::Core.new(build, user))
end
describe '#illustration' do
it { expect(subject.illustration).to include(:image, :size, :title, :content) }
end
describe '.matches?' do
subject {described_class.matches?(build, user) }
context 'when build is manual' do
let(:build) { create(:ci_build, :manual) }
it 'is a correct match' do
expect(subject).to be true
end
end
context 'when build is not manual' do
let(:build) { create(:ci_build) }
it 'does not match' do
expect(subject).to be false
end
end
end
end

View File

@ -0,0 +1,33 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Build::Pending do
let(:user) { create(:user) }
subject do
described_class.new(double('subject'))
end
describe '#illustration' do
it { expect(subject.illustration).to include(:image, :size, :title, :content) }
end
describe '.matches?' do
subject {described_class.matches?(build, user) }
context 'when build is pending' do
let(:build) { create(:ci_build, :pending) }
it 'is a correct match' do
expect(subject).to be true
end
end
context 'when build is not pending' do
let(:build) { create(:ci_build, :success) }
it 'does not match' do
expect(subject).to be false
end
end
end
end

View File

@ -69,6 +69,10 @@ describe Gitlab::Ci::Status::Build::Play do
it { expect(subject.action_title).to eq 'Play' } it { expect(subject.action_title).to eq 'Play' }
end end
describe '#action_button_title' do
it { expect(subject.action_button_title).to eq 'Trigger this manual action' }
end
describe '.matches?' do describe '.matches?' do
subject { described_class.matches?(build, user) } subject { described_class.matches?(build, user) }

View File

@ -90,6 +90,10 @@ describe Gitlab::Ci::Status::Build::Retryable do
describe '#action_title' do describe '#action_title' do
it { expect(subject.action_title).to eq 'Retry' } it { expect(subject.action_title).to eq 'Retry' }
end end
describe '#action_button_title' do
it { expect(subject.action_button_title).to eq 'Retry this job' }
end
end end
describe '.matches?' do describe '.matches?' do

View File

@ -0,0 +1,33 @@
require 'spec_helper'
describe Gitlab::Ci::Status::Build::Skipped do
let(:user) { create(:user) }
subject do
described_class.new(double('subject'))
end
describe '#illustration' do
it { expect(subject.illustration).to include(:image, :size, :title) }
end
describe '.matches?' do
subject {described_class.matches?(build, user) }
context 'when build is skipped' do
let(:build) { create(:ci_build, :skipped) }
it 'is a correct match' do
expect(subject).to be true
end
end
context 'when build is not skipped' do
let(:build) { create(:ci_build) }
it 'does not match' do
expect(subject).to be false
end
end
end
end

View File

@ -44,6 +44,10 @@ describe Gitlab::Ci::Status::Build::Stop do
describe '#action_title' do describe '#action_title' do
it { expect(subject.action_title).to eq 'Stop' } it { expect(subject.action_title).to eq 'Stop' }
end end
describe '#action_button_title' do
it { expect(subject.action_button_title).to eq 'Stop this environment' }
end
end end
describe '.matches?' do describe '.matches?' do

View File

@ -21,7 +21,7 @@ describe 'projects/jobs/show' do
describe 'environment info in job view' do describe 'environment info in job view' do
context 'job with latest deployment' do context 'job with latest deployment' do
let(:build) do let(:build) do
create(:ci_build, :success, environment: 'staging') create(:ci_build, :success, :trace_artifact, environment: 'staging')
end end
before do before do
@ -40,11 +40,11 @@ describe 'projects/jobs/show' do
context 'job with outdated deployment' do context 'job with outdated deployment' do
let(:build) do let(:build) do
create(:ci_build, :success, environment: 'staging', pipeline: pipeline) create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline)
end end
let(:second_build) do let(:second_build) do
create(:ci_build, :success, environment: 'staging', pipeline: pipeline) create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline)
end end
let(:environment) do let(:environment) do
@ -70,7 +70,7 @@ describe 'projects/jobs/show' do
context 'job failed to deploy' do context 'job failed to deploy' do
let(:build) do let(:build) do
create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline)
end end
let!(:environment) do let!(:environment) do
@ -88,7 +88,7 @@ describe 'projects/jobs/show' do
context 'job will deploy' do context 'job will deploy' do
let(:build) do let(:build) do
create(:ci_build, :running, environment: 'staging', pipeline: pipeline) create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline)
end end
context 'when environment exists' do context 'when environment exists' do
@ -136,7 +136,7 @@ describe 'projects/jobs/show' do
context 'job that failed to deploy and environment has not been created' do context 'job that failed to deploy and environment has not been created' do
let(:build) do let(:build) do
create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline)
end end
let!(:environment) do let!(:environment) do
@ -154,7 +154,7 @@ describe 'projects/jobs/show' do
context 'job that will deploy and environment has not been created' do context 'job that will deploy and environment has not been created' do
let(:build) do let(:build) do
create(:ci_build, :running, environment: 'staging', pipeline: pipeline) create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline)
end end
let!(:environment) do let!(:environment) do
@ -174,8 +174,9 @@ describe 'projects/jobs/show' do
end end
context 'when job is running' do context 'when job is running' do
let(:build) { create(:ci_build, :trace_live, :running, pipeline: pipeline) }
before do before do
build.run!
render render
end end