Merge remote-tracking branch 'upstream/master' into show-commit-status-from-latest-pipeline
* upstream/master: (39 commits) Improve build status specs contexts descriptions Add some missing tests for detailed status methods Remove trailing blank line from Allowable module Update manual build icon SVG Make it possible to mix `Gitlab::Routing` in Extract abilities checking module from ability model Extend tests for pipeline detailed status helpers Add tests for common build detailed status helpers Add missing tests for build `cancelable?` method Add tests for detailed build statuses factory Make it possible to retry build that was canceled Make build retryable only if complete and executed Improve readability in methods for detailed status Add tests for build cancelable/retryable statuses Extend specs for build play/stop detailed statuses Refine build stop/play extended status specs Use manual build icon in play/stop build statuses Adds manual action icon and case to show it Fix detailed status specs for pipeline stage model Fix detailed status badge for generic commit status ...
This commit is contained in:
commit
3ce6ba7db9
58 changed files with 1126 additions and 171 deletions
|
@ -4,25 +4,7 @@ module CiStatusHelper
|
|||
builds_namespace_project_commit_path(project.namespace, project, pipeline.sha)
|
||||
end
|
||||
|
||||
def ci_status_with_icon(status, target = nil)
|
||||
content = ci_icon_for_status(status) + ci_text_for_status(status)
|
||||
klass = "ci-status ci-#{status}"
|
||||
|
||||
if target
|
||||
link_to content, target, class: klass
|
||||
else
|
||||
content_tag :span, content, class: klass
|
||||
end
|
||||
end
|
||||
|
||||
def ci_text_for_status(status)
|
||||
if detailed_status?(status)
|
||||
status.text
|
||||
else
|
||||
status
|
||||
end
|
||||
end
|
||||
|
||||
# Is used by Commit and Merge Request Widget
|
||||
def ci_label_for_status(status)
|
||||
if detailed_status?(status)
|
||||
return status.label
|
||||
|
|
|
@ -100,6 +100,12 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Build::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
|
||||
def manual?
|
||||
self.when == 'manual'
|
||||
end
|
||||
|
@ -123,8 +129,13 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def cancelable?
|
||||
active?
|
||||
end
|
||||
|
||||
def retryable?
|
||||
project.builds_enabled? && commands.present? && complete?
|
||||
project.builds_enabled? && commands.present? &&
|
||||
(success? || failed? || canceled?)
|
||||
end
|
||||
|
||||
def retried?
|
||||
|
@ -148,7 +159,7 @@ module Ci
|
|||
end
|
||||
|
||||
def environment_action
|
||||
self.options.fetch(:environment, {}).fetch(:action, 'start')
|
||||
self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options
|
||||
end
|
||||
|
||||
def outdated_deployment?
|
||||
|
|
|
@ -346,8 +346,10 @@ module Ci
|
|||
.select { |merge_request| merge_request.head_pipeline.try(:id) == self.id }
|
||||
end
|
||||
|
||||
def detailed_status
|
||||
Gitlab::Ci::Status::Pipeline::Factory.new(self).fabricate!
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Pipeline::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -22,8 +22,10 @@ module Ci
|
|||
@status ||= statuses.latest.status
|
||||
end
|
||||
|
||||
def detailed_status
|
||||
Gitlab::Ci::Status::Stage::Factory.new(self).fabricate!
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Stage::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
|
||||
def statuses
|
||||
|
|
|
@ -131,4 +131,10 @@ class CommitStatus < ActiveRecord::Base
|
|||
def has_trace?
|
||||
false
|
||||
end
|
||||
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
%strong ##{build.id}
|
||||
|
||||
%td.status
|
||||
= ci_status_with_icon(build.status)
|
||||
= render 'ci/status/badge', status: build.detailed_status(current_user)
|
||||
|
||||
%td.status
|
||||
- if project
|
||||
|
|
10
app/views/ci/status/_badge.html.haml
Normal file
10
app/views/ci/status/_badge.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
- status = local_assigns.fetch(:status)
|
||||
|
||||
- if status.has_details?
|
||||
= link_to status.details_path, class: "ci-status ci-#{status}" do
|
||||
= custom_icon(status.icon)
|
||||
= status.text
|
||||
- else
|
||||
%span{ class: "ci-status ci-#{status}" }
|
||||
= custom_icon(status.icon)
|
||||
= status.text
|
|
@ -1,6 +1,6 @@
|
|||
.content-block.build-header
|
||||
.header-content
|
||||
= ci_status_with_icon(@build.status)
|
||||
= render 'ci/status/badge', status: @build.detailed_status(current_user)
|
||||
Build
|
||||
%strong ##{@build.id}
|
||||
in pipeline
|
||||
|
|
|
@ -9,10 +9,7 @@
|
|||
|
||||
%tr.build.commit{class: ('retried' if retried)}
|
||||
%td.status
|
||||
- if can?(current_user, :read_build, build)
|
||||
= ci_status_with_icon(build.status, namespace_project_build_url(build.project.namespace, build.project, build))
|
||||
- else
|
||||
= ci_status_with_icon(build.status)
|
||||
= render "ci/status/badge", status: build.detailed_status(current_user)
|
||||
|
||||
%td.branch-commit
|
||||
- if can?(current_user, :read_build, build)
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
- status = pipeline.status
|
||||
- detailed_status = pipeline.detailed_status
|
||||
- show_commit = local_assigns.fetch(:show_commit, true)
|
||||
- show_branch = local_assigns.fetch(:show_branch, true)
|
||||
|
||||
%tr.commit
|
||||
%td.commit-link
|
||||
= link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: "ci-status ci-#{detailed_status}" do
|
||||
= ci_icon_for_status(detailed_status)
|
||||
= ci_text_for_status(detailed_status)
|
||||
= render 'ci/status/badge', status: pipeline.detailed_status(current_user)
|
||||
|
||||
%td
|
||||
= link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
|
||||
%tr.generic_commit_status{class: ('retried' if retried)}
|
||||
%td.status
|
||||
- if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url
|
||||
= ci_status_with_icon(generic_commit_status.status, generic_commit_status.target_url)
|
||||
- else
|
||||
= ci_status_with_icon(generic_commit_status.status)
|
||||
= render 'ci/status/badge', status: generic_commit_status.detailed_status(current_user)
|
||||
|
||||
%td.generic_commit_status-link
|
||||
- if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.page-content-header
|
||||
.header-main-content
|
||||
= ci_status_with_icon(@pipeline.detailed_status)
|
||||
= render 'ci/status/badge', status: @pipeline.detailed_status(current_user)
|
||||
%strong Pipeline ##{@commit.pipelines.last.id}
|
||||
triggered #{time_ago_with_tooltip(@commit.authored_date)} by
|
||||
= author_avatar(@commit, size: 24)
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
%li.build
|
||||
.curve
|
||||
.dropdown.inline.build-content
|
||||
= render "projects/stage/in_stage_group", name: group_name, subject: grouped_statuses
|
||||
= render 'projects/stage/in_stage_group', name: group_name, subject: grouped_statuses
|
||||
|
|
1
app/views/shared/icons/_icon_status_manual.svg
Executable file
1
app/views/shared/icons/_icon_status_manual.svg
Executable file
|
@ -0,0 +1 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M10.5 7.63V6.37l-.787-.13c-.044-.175-.132-.349-.263-.61l.481-.652-.918-.913-.657.478a2.346 2.346 0 0 0-.612-.26L7.656 3.5H6.388l-.132.783c-.219.043-.394.13-.612.26l-.657-.478-.918.913.437.652c-.131.218-.175.392-.262.61l-.744.086v1.261l.787.13c.044.218.132.392.263.61l-.438.651.92.913.655-.434c.175.086.394.173.613.26l.131.783h1.313l.131-.783c.219-.043.394-.13.613-.26l.656.478.918-.913-.48-.652c.13-.218.218-.435.262-.61l.656-.13zM7 8.283a1.285 1.285 0 0 1-1.313-1.305c0-.739.57-1.304 1.313-1.304.744 0 1.313.565 1.313 1.304 0 .74-.57 1.305-1.313 1.305z"/></g></svg>
|
After Width: | Height: | Size: 787 B |
7
lib/gitlab/allowable.rb
Normal file
7
lib/gitlab/allowable.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
module Gitlab
|
||||
module Allowable
|
||||
def can?(user, action, subject)
|
||||
Ability.allowed?(user, action, subject)
|
||||
end
|
||||
end
|
||||
end
|
37
lib/gitlab/ci/status/build/cancelable.rb
Normal file
37
lib/gitlab/ci/status/build/cancelable.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Cancelable < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'ban'
|
||||
end
|
||||
|
||||
def action_path
|
||||
cancel_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Cancel'
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.cancelable?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
19
lib/gitlab/ci/status/build/common.rb
Normal file
19
lib/gitlab/ci/status/build/common.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
module Common
|
||||
def has_details?
|
||||
can?(user, :read_build, subject)
|
||||
end
|
||||
|
||||
def details_path
|
||||
namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
lib/gitlab/ci/status/build/factory.rb
Normal file
18
lib/gitlab/ci/status/build/factory.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Factory < Status::Factory
|
||||
def self.extended_statuses
|
||||
[Status::Build::Stop, Status::Build::Play,
|
||||
Status::Build::Cancelable, Status::Build::Retryable]
|
||||
end
|
||||
|
||||
def self.common_helpers
|
||||
Status::Build::Common
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
53
lib/gitlab/ci/status/build/play.rb
Normal file
53
lib/gitlab/ci/status/build/play.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Play < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def text
|
||||
'manual'
|
||||
end
|
||||
|
||||
def label
|
||||
'manual play action'
|
||||
end
|
||||
|
||||
def icon
|
||||
'icon_status_manual'
|
||||
end
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'play'
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Play'
|
||||
end
|
||||
|
||||
def action_class
|
||||
'ci-play-icon'
|
||||
end
|
||||
|
||||
def action_path
|
||||
play_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.playable? && !build.stops_environment?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
37
lib/gitlab/ci/status/build/retryable.rb
Normal file
37
lib/gitlab/ci/status/build/retryable.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Retryable < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'refresh'
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Retry'
|
||||
end
|
||||
|
||||
def action_path
|
||||
retry_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.retryable?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
49
lib/gitlab/ci/status/build/stop.rb
Normal file
49
lib/gitlab/ci/status/build/stop.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Stop < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def text
|
||||
'manual'
|
||||
end
|
||||
|
||||
def label
|
||||
'manual stop action'
|
||||
end
|
||||
|
||||
def icon
|
||||
'icon_status_manual'
|
||||
end
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'stop'
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Stop'
|
||||
end
|
||||
|
||||
def action_path
|
||||
play_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.playable? && build.stops_environment?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,10 +4,14 @@ module Gitlab
|
|||
# Base abstract class fore core status
|
||||
#
|
||||
class Core
|
||||
include Gitlab::Routing.url_helpers
|
||||
include Gitlab::Routing
|
||||
include Gitlab::Allowable
|
||||
|
||||
def initialize(subject)
|
||||
attr_reader :subject, :user
|
||||
|
||||
def initialize(subject, user)
|
||||
@subject = subject
|
||||
@user = user
|
||||
end
|
||||
|
||||
def icon
|
||||
|
@ -18,10 +22,6 @@ module Gitlab
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def title
|
||||
"#{@subject.class.name.demodulize}: #{label}"
|
||||
end
|
||||
|
||||
# Deprecation warning: this method is here because we need to maintain
|
||||
# backwards compatibility with legacy statuses. We often do something
|
||||
# like "ci-status ci-status-#{status}" to set CSS class.
|
||||
|
@ -34,7 +34,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def has_details?
|
||||
raise NotImplementedError
|
||||
false
|
||||
end
|
||||
|
||||
def details_path
|
||||
|
@ -42,16 +42,27 @@ module Gitlab
|
|||
end
|
||||
|
||||
def has_action?
|
||||
raise NotImplementedError
|
||||
false
|
||||
end
|
||||
|
||||
def action_icon
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def action_class
|
||||
end
|
||||
|
||||
def action_path
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def action_method
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def action_title
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,10 +2,14 @@ module Gitlab
|
|||
module Ci
|
||||
module Status
|
||||
module Extended
|
||||
def matches?(_subject)
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
class_methods do
|
||||
def matches?(_subject, _user)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,10 +2,9 @@ module Gitlab
|
|||
module Ci
|
||||
module Status
|
||||
class Factory
|
||||
attr_reader :subject
|
||||
|
||||
def initialize(subject)
|
||||
def initialize(subject, user)
|
||||
@subject = subject
|
||||
@user = user
|
||||
end
|
||||
|
||||
def fabricate!
|
||||
|
@ -16,27 +15,32 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def self.extended_statuses
|
||||
[]
|
||||
end
|
||||
|
||||
def self.common_helpers
|
||||
Module.new
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def subject_status
|
||||
@subject_status ||= subject.status
|
||||
def simple_status
|
||||
@simple_status ||= @subject.status || :created
|
||||
end
|
||||
|
||||
def core_status
|
||||
Gitlab::Ci::Status
|
||||
.const_get(subject_status.capitalize)
|
||||
.new(subject)
|
||||
.const_get(simple_status.capitalize)
|
||||
.new(@subject, @user)
|
||||
.extend(self.class.common_helpers)
|
||||
end
|
||||
|
||||
def extended_status
|
||||
@extended ||= extended_statuses.find do |status|
|
||||
status.matches?(subject)
|
||||
@extended ||= self.class.extended_statuses.find do |status|
|
||||
status.matches?(@subject, @user)
|
||||
end
|
||||
end
|
||||
|
||||
def extended_statuses
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,13 +4,13 @@ module Gitlab
|
|||
module Pipeline
|
||||
module Common
|
||||
def has_details?
|
||||
true
|
||||
can?(user, :read_pipeline, subject)
|
||||
end
|
||||
|
||||
def details_path
|
||||
namespace_project_pipeline_path(@subject.project.namespace,
|
||||
@subject.project,
|
||||
@subject)
|
||||
namespace_project_pipeline_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def has_action?
|
||||
|
|
|
@ -3,14 +3,12 @@ module Gitlab
|
|||
module Status
|
||||
module Pipeline
|
||||
class Factory < Status::Factory
|
||||
private
|
||||
|
||||
def extended_statuses
|
||||
def self.extended_statuses
|
||||
[Pipeline::SuccessWithWarnings]
|
||||
end
|
||||
|
||||
def core_status
|
||||
super.extend(Status::Pipeline::Common)
|
||||
def self.common_helpers
|
||||
Status::Pipeline::Common
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ module Gitlab
|
|||
module Status
|
||||
module Pipeline
|
||||
class SuccessWithWarnings < SimpleDelegator
|
||||
extend Status::Extended
|
||||
include Status::Extended
|
||||
|
||||
def text
|
||||
'passed'
|
||||
|
@ -21,7 +21,7 @@ module Gitlab
|
|||
'success_with_warnings'
|
||||
end
|
||||
|
||||
def self.matches?(pipeline)
|
||||
def self.matches?(pipeline, user)
|
||||
pipeline.success? && pipeline.has_warnings?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,14 +4,14 @@ module Gitlab
|
|||
module Stage
|
||||
module Common
|
||||
def has_details?
|
||||
true
|
||||
can?(user, :read_pipeline, subject.pipeline)
|
||||
end
|
||||
|
||||
def details_path
|
||||
namespace_project_pipeline_path(@subject.project.namespace,
|
||||
@subject.project,
|
||||
@subject.pipeline,
|
||||
anchor: @subject.name)
|
||||
namespace_project_pipeline_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject.pipeline,
|
||||
anchor: subject.name)
|
||||
end
|
||||
|
||||
def has_action?
|
||||
|
|
|
@ -3,10 +3,8 @@ module Gitlab
|
|||
module Status
|
||||
module Stage
|
||||
class Factory < Status::Factory
|
||||
private
|
||||
|
||||
def core_status
|
||||
super.extend(Status::Stage::Common)
|
||||
def self.common_helpers
|
||||
Status::Stage::Common
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
module Gitlab
|
||||
module Routing
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include Gitlab::Routing.url_helpers
|
||||
end
|
||||
|
||||
# Returns the URL helpers Module.
|
||||
#
|
||||
# This method caches the output as Rails' "url_helpers" method creates an
|
||||
|
|
|
@ -12,12 +12,14 @@ FactoryGirl.define do
|
|||
started_at 'Di 29. Okt 09:51:28 CET 2013'
|
||||
finished_at 'Di 29. Okt 09:53:28 CET 2013'
|
||||
commands 'ls -a'
|
||||
|
||||
options do
|
||||
{
|
||||
image: "ruby:2.1",
|
||||
services: ["postgres"]
|
||||
}
|
||||
end
|
||||
|
||||
yaml_variables do
|
||||
[
|
||||
{ key: :DB_NAME, value: 'postgres', public: true }
|
||||
|
@ -60,15 +62,20 @@ FactoryGirl.define do
|
|||
end
|
||||
|
||||
trait :teardown_environment do
|
||||
options do
|
||||
{ environment: { action: 'stop' } }
|
||||
end
|
||||
environment 'staging'
|
||||
options environment: { name: 'staging',
|
||||
action: 'stop' }
|
||||
end
|
||||
|
||||
trait :allowed_to_fail do
|
||||
allow_failure true
|
||||
end
|
||||
|
||||
trait :playable do
|
||||
skipped
|
||||
manual
|
||||
end
|
||||
|
||||
after(:build) do |build, evaluator|
|
||||
build.project = build.pipeline.project
|
||||
end
|
||||
|
|
27
spec/lib/gitlab/allowable_spec.rb
Normal file
27
spec/lib/gitlab/allowable_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Allowable do
|
||||
subject do
|
||||
Class.new.include(described_class).new
|
||||
end
|
||||
|
||||
describe '#can?' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
context 'when user is allowed to do something' do
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
|
||||
it 'reports correct ability to perform action' do
|
||||
expect(subject.can?(user, :read_project, project)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not allowed to do something' do
|
||||
let(:project) { create(:empty_project, :private) }
|
||||
|
||||
it 'reports correct ability to perform action' do
|
||||
expect(subject.can?(user, :read_project, project)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
86
spec/lib/gitlab/ci/status/build/cancelable_spec.rb
Normal file
86
spec/lib/gitlab/ci/status/build/cancelable_spec.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Cancelable do
|
||||
let(:status) { double('core status') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject do
|
||||
described_class.new(status)
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it 'does not override status text' do
|
||||
expect(status).to receive(:text)
|
||||
|
||||
subject.text
|
||||
end
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it 'does not override status icon' do
|
||||
expect(status).to receive(:icon)
|
||||
|
||||
subject.icon
|
||||
end
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it 'does not override status label' do
|
||||
expect(status).to receive(:label)
|
||||
|
||||
subject.label
|
||||
end
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/cancel" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'ban' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Cancel' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is cancelable' do
|
||||
let(:build) do
|
||||
create(:ci_build, :running)
|
||||
end
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not cancelable' do
|
||||
let(:build) { create(:ci_build, :success) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
37
spec/lib/gitlab/ci/status/build/common_spec.rb
Normal file
37
spec/lib/gitlab/ci/status/build/common_spec.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Common do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:project) { build.project }
|
||||
|
||||
subject do
|
||||
Gitlab::Ci::Status::Core
|
||||
.new(build, user)
|
||||
.extend(described_class)
|
||||
end
|
||||
|
||||
describe '#has_action?' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
|
||||
describe '#has_details?' do
|
||||
context 'when user has access to read build' do
|
||||
before { project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_details }
|
||||
end
|
||||
|
||||
context 'when user does not have access to read build' do
|
||||
before { project.update(public_builds: false) }
|
||||
|
||||
it { is_expected.not_to have_details }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#details_path' do
|
||||
it 'links to the build details page' do
|
||||
expect(subject.details_path).to include "builds/#{build.id}"
|
||||
end
|
||||
end
|
||||
end
|
141
spec/lib/gitlab/ci/status/build/factory_spec.rb
Normal file
141
spec/lib/gitlab/ci/status/build/factory_spec.rb
Normal file
|
@ -0,0 +1,141 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Factory do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { build.project }
|
||||
|
||||
subject { described_class.new(build, user) }
|
||||
let(:status) { subject.fabricate! }
|
||||
|
||||
before { project.team << [user, :developer] }
|
||||
|
||||
context 'when build is successful' do
|
||||
let(:build) { create(:ci_build, :success) }
|
||||
|
||||
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 'icon_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
|
||||
let(:build) { create(:ci_build, :failed) }
|
||||
|
||||
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 'failed'
|
||||
expect(status.icon).to eq 'icon_status_failed'
|
||||
expect(status.label).to eq 'failed'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is a canceled' do
|
||||
let(:build) { create(:ci_build, :canceled) }
|
||||
|
||||
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 'canceled'
|
||||
expect(status.icon).to eq 'icon_status_canceled'
|
||||
expect(status.label).to eq 'canceled'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is running' do
|
||||
let(:build) { create(:ci_build, :running) }
|
||||
|
||||
it 'fabricates a canceable build status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Cancelable
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'running'
|
||||
expect(status.icon).to eq 'icon_status_running'
|
||||
expect(status.label).to eq 'running'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is pending' do
|
||||
let(:build) { create(:ci_build, :pending) }
|
||||
|
||||
it 'fabricates a cancelable build status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Cancelable
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'pending'
|
||||
expect(status.icon).to eq 'icon_status_pending'
|
||||
expect(status.label).to eq 'pending'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is skipped' do
|
||||
let(:build) { create(:ci_build, :skipped) }
|
||||
|
||||
it 'fabricates a core skipped status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Skipped
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'skipped'
|
||||
expect(status.icon).to eq 'icon_status_skipped'
|
||||
expect(status.label).to eq 'skipped'
|
||||
expect(status).to have_details
|
||||
expect(status).not_to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is a manual action' do
|
||||
context 'when build is a play action' do
|
||||
let(:build) { create(:ci_build, :playable) }
|
||||
|
||||
it 'fabricates a core skipped status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Play
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'manual'
|
||||
expect(status.icon).to eq 'icon_status_manual'
|
||||
expect(status.label).to eq 'manual play action'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is an environment stop action' do
|
||||
let(:build) { create(:ci_build, :playable, :teardown_environment) }
|
||||
|
||||
it 'fabricates a core skipped status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Stop
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'manual'
|
||||
expect(status.icon).to eq 'icon_status_manual'
|
||||
expect(status.label).to eq 'manual stop action'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
82
spec/lib/gitlab/ci/status/build/play_spec.rb
Normal file
82
spec/lib/gitlab/ci/status/build/play_spec.rb
Normal file
|
@ -0,0 +1,82 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Play do
|
||||
let(:status) { double('core') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject { described_class.new(status) }
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.text).to eq 'manual' }
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it { expect(subject.label).to eq 'manual play action' }
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_manual' }
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/play" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'play' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Play' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is playable' do
|
||||
context 'when build stops an environment' do
|
||||
let(:build) do
|
||||
create(:ci_build, :playable, :teardown_environment)
|
||||
end
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build does not stop an environment' do
|
||||
let(:build) { create(:ci_build, :playable) }
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not playable' do
|
||||
let(:build) { create(:ci_build) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
86
spec/lib/gitlab/ci/status/build/retryable_spec.rb
Normal file
86
spec/lib/gitlab/ci/status/build/retryable_spec.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Retryable do
|
||||
let(:status) { double('core status') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject do
|
||||
described_class.new(status)
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it 'does not override status text' do
|
||||
expect(status).to receive(:text)
|
||||
|
||||
subject.text
|
||||
end
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it 'does not override status icon' do
|
||||
expect(status).to receive(:icon)
|
||||
|
||||
subject.icon
|
||||
end
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it 'does not override status label' do
|
||||
expect(status).to receive(:label)
|
||||
|
||||
subject.label
|
||||
end
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/retry" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'refresh' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Retry' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is retryable' do
|
||||
let(:build) do
|
||||
create(:ci_build, :success)
|
||||
end
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not retryable' do
|
||||
let(:build) { create(:ci_build, :running) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
84
spec/lib/gitlab/ci/status/build/stop_spec.rb
Normal file
84
spec/lib/gitlab/ci/status/build/stop_spec.rb
Normal file
|
@ -0,0 +1,84 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Stop do
|
||||
let(:status) { double('core status') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject do
|
||||
described_class.new(status)
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.text).to eq 'manual' }
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it { expect(subject.label).to eq 'manual stop action' }
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_manual' }
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/play" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'stop' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Stop' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is playable' do
|
||||
context 'when build stops an environment' do
|
||||
let(:build) do
|
||||
create(:ci_build, :playable, :teardown_environment)
|
||||
end
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build does not stop an environment' do
|
||||
let(:build) { create(:ci_build, :playable) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not playable' do
|
||||
let(:build) { create(:ci_build) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Canceled do
|
||||
subject { described_class.new(double('subject')) }
|
||||
subject do
|
||||
described_class.new(double('subject'), double('user'))
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.label).to eq 'canceled' }
|
||||
|
@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Canceled do
|
|||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_canceled' }
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
it { expect(subject.title).to eq 'Double: canceled' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Created do
|
||||
subject { described_class.new(double('subject')) }
|
||||
subject do
|
||||
described_class.new(double('subject'), double('user'))
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.label).to eq 'created' }
|
||||
|
@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Created do
|
|||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_created' }
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
it { expect(subject.title).to eq 'Double: created' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,11 +2,11 @@ require 'spec_helper'
|
|||
|
||||
describe Gitlab::Ci::Status::Extended do
|
||||
subject do
|
||||
Class.new.extend(described_class)
|
||||
Class.new.include(described_class)
|
||||
end
|
||||
|
||||
it 'requires subclass to implement matcher' do
|
||||
expect { subject.matches?(double) }
|
||||
expect { subject.matches?(double, double) }
|
||||
.to raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,15 +2,17 @@ require 'spec_helper'
|
|||
|
||||
describe Gitlab::Ci::Status::Factory do
|
||||
subject do
|
||||
described_class.new(object)
|
||||
described_class.new(resource, user)
|
||||
end
|
||||
|
||||
let(:user) { create(:user) }
|
||||
|
||||
let(:status) { subject.fabricate! }
|
||||
|
||||
context 'when object has a core status' do
|
||||
HasStatus::AVAILABLE_STATUSES.each do |core_status|
|
||||
context "when core status is #{core_status}" do
|
||||
let(:object) { double(status: core_status) }
|
||||
let(:resource) { double(status: core_status) }
|
||||
|
||||
it "fabricates a core status #{core_status}" do
|
||||
expect(status).to be_a(
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Failed do
|
||||
subject { described_class.new(double('subject')) }
|
||||
subject do
|
||||
described_class.new(double('subject'), double('user'))
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.label).to eq 'failed' }
|
||||
|
@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Failed do
|
|||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_failed' }
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
it { expect(subject.title).to eq 'Double: failed' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Pending do
|
||||
subject { described_class.new(double('subject')) }
|
||||
subject do
|
||||
described_class.new(double('subject'), double('user'))
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.label).to eq 'pending' }
|
||||
|
@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Pending do
|
|||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_pending' }
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
it { expect(subject.title).to eq 'Double: pending' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,23 +1,36 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Pipeline::Common do
|
||||
let(:pipeline) { create(:ci_pipeline) }
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:empty_project, :private) }
|
||||
let(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
|
||||
subject do
|
||||
Class.new(Gitlab::Ci::Status::Core)
|
||||
.new(pipeline).extend(described_class)
|
||||
Gitlab::Ci::Status::Core
|
||||
.new(pipeline, user)
|
||||
.extend(described_class)
|
||||
end
|
||||
|
||||
it 'does not have action' do
|
||||
expect(subject).not_to have_action
|
||||
describe '#has_action?' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
|
||||
it 'has details' do
|
||||
expect(subject).to have_details
|
||||
describe '#has_details?' do
|
||||
context 'when user has access to read pipeline' do
|
||||
before { project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_details }
|
||||
end
|
||||
|
||||
context 'when user does not have access to read pipeline' do
|
||||
it { is_expected.not_to have_details }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#details_path' do
|
||||
it 'links to the pipeline details page' do
|
||||
expect(subject.details_path)
|
||||
.to include "pipelines/#{pipeline.id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Pipeline::Factory do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { pipeline.project }
|
||||
|
||||
subject do
|
||||
described_class.new(pipeline)
|
||||
described_class.new(pipeline, user)
|
||||
end
|
||||
|
||||
let(:status) do
|
||||
subject.fabricate!
|
||||
end
|
||||
|
||||
before do
|
||||
project.team << [user, :developer]
|
||||
end
|
||||
|
||||
context 'when pipeline has a core status' do
|
||||
HasStatus::AVAILABLE_STATUSES.each do |core_status|
|
||||
context "when core status is #{core_status}" do
|
||||
|
|
|
@ -29,13 +29,13 @@ describe Gitlab::Ci::Status::Pipeline::SuccessWithWarnings do
|
|||
end
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(described_class.matches?(pipeline)).to eq true
|
||||
expect(described_class.matches?(pipeline, double)).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pipeline does not have warnings' do
|
||||
it 'does not match' do
|
||||
expect(described_class.matches?(pipeline)).to eq false
|
||||
expect(described_class.matches?(pipeline, double)).to eq false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -51,13 +51,13 @@ describe Gitlab::Ci::Status::Pipeline::SuccessWithWarnings do
|
|||
end
|
||||
|
||||
it 'does not match' do
|
||||
expect(described_class.matches?(pipeline)).to eq false
|
||||
expect(described_class.matches?(pipeline, double)).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pipeline does not have warnings' do
|
||||
it 'does not match' do
|
||||
expect(described_class.matches?(pipeline)).to eq false
|
||||
expect(described_class.matches?(pipeline, double)).to eq false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Running do
|
||||
subject { described_class.new(double('subject')) }
|
||||
subject do
|
||||
described_class.new(double('subject'), double('user'))
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.label).to eq 'running' }
|
||||
|
@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Running do
|
|||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_running' }
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
it { expect(subject.title).to eq 'Double: running' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Skipped do
|
||||
subject { described_class.new(double('subject')) }
|
||||
subject do
|
||||
described_class.new(double('subject'), double('user'))
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.label).to eq 'skipped' }
|
||||
|
@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Skipped do
|
|||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_skipped' }
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
it { expect(subject.title).to eq 'Double: skipped' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,26 +1,43 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Stage::Common do
|
||||
let(:pipeline) { create(:ci_empty_pipeline) }
|
||||
let(:stage) { build(:ci_stage, pipeline: pipeline, name: 'test') }
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
|
||||
|
||||
let(:stage) do
|
||||
build(:ci_stage, pipeline: pipeline, name: 'test')
|
||||
end
|
||||
|
||||
subject do
|
||||
Class.new(Gitlab::Ci::Status::Core)
|
||||
.new(stage).extend(described_class)
|
||||
.new(stage, user).extend(described_class)
|
||||
end
|
||||
|
||||
it 'does not have action' do
|
||||
expect(subject).not_to have_action
|
||||
end
|
||||
|
||||
it 'has details' do
|
||||
expect(subject).to have_details
|
||||
end
|
||||
|
||||
it 'links to the pipeline details page' do
|
||||
expect(subject.details_path)
|
||||
.to include "pipelines/#{pipeline.id}"
|
||||
expect(subject.details_path)
|
||||
.to include "##{stage.name}"
|
||||
end
|
||||
|
||||
context 'when user has permission to read pipeline' do
|
||||
before do
|
||||
project.team << [user, :master]
|
||||
end
|
||||
|
||||
it 'has details' do
|
||||
expect(subject).to have_details
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user does not have permission to read pipeline' do
|
||||
it 'does not have details' do
|
||||
expect(subject).not_to have_details
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Stage::Factory do
|
||||
let(:pipeline) { create(:ci_empty_pipeline) }
|
||||
let(:stage) { build(:ci_stage, pipeline: pipeline, name: 'test') }
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
|
||||
|
||||
let(:stage) do
|
||||
build(:ci_stage, pipeline: pipeline, name: 'test')
|
||||
end
|
||||
|
||||
subject do
|
||||
described_class.new(stage)
|
||||
described_class.new(stage, user)
|
||||
end
|
||||
|
||||
let(:status) do
|
||||
subject.fabricate!
|
||||
end
|
||||
|
||||
before do
|
||||
project.team << [user, :developer]
|
||||
end
|
||||
|
||||
context 'when stage has a core status' do
|
||||
HasStatus::AVAILABLE_STATUSES.each do |core_status|
|
||||
context "when core status is #{core_status}" do
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Success do
|
||||
subject { described_class.new(double('subject')) }
|
||||
subject do
|
||||
described_class.new(double('subject'), double('user'))
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.label).to eq 'passed' }
|
||||
|
@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Success do
|
|||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_success' }
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
it { expect(subject.title).to eq 'Double: passed' }
|
||||
end
|
||||
end
|
||||
|
|
23
spec/lib/gitlab/routing_spec.rb
Normal file
23
spec/lib/gitlab/routing_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Routing do
|
||||
context 'when module is included' do
|
||||
subject do
|
||||
Class.new.include(described_class).new
|
||||
end
|
||||
|
||||
it 'makes it possible to access url helpers' do
|
||||
expect(subject).to respond_to(:namespace_project_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when module is not included' do
|
||||
subject do
|
||||
Class.new.include(described_class.url_helpers).new
|
||||
end
|
||||
|
||||
it 'exposes url helpers module through a method' do
|
||||
expect(subject).to respond_to(:namespace_project_path)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -899,21 +899,87 @@ describe Ci::Build, models: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#retryable?' do
|
||||
describe '#cancelable?' do
|
||||
subject { build }
|
||||
|
||||
context 'when build is cancelable' do
|
||||
context 'when build is pending' do
|
||||
it { is_expected.to be_cancelable }
|
||||
end
|
||||
|
||||
context 'when build is running' do
|
||||
before do
|
||||
build.run!
|
||||
end
|
||||
|
||||
it { expect(build).not_to be_retryable }
|
||||
it { is_expected.to be_cancelable }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is finished' do
|
||||
context 'when build is not cancelable' do
|
||||
context 'when build is successful' do
|
||||
before do
|
||||
build.success!
|
||||
end
|
||||
|
||||
it { expect(build).to be_retryable }
|
||||
it { is_expected.not_to be_cancelable }
|
||||
end
|
||||
|
||||
context 'when build is failed' do
|
||||
before do
|
||||
build.drop!
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_cancelable }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#retryable?' do
|
||||
subject { build }
|
||||
|
||||
context 'when build is retryable' do
|
||||
context 'when build is successful' do
|
||||
before do
|
||||
build.success!
|
||||
end
|
||||
|
||||
it { is_expected.to be_retryable }
|
||||
end
|
||||
|
||||
context 'when build is failed' do
|
||||
before do
|
||||
build.drop!
|
||||
end
|
||||
|
||||
it { is_expected.to be_retryable }
|
||||
end
|
||||
|
||||
context 'when build is canceled' do
|
||||
before do
|
||||
build.cancel!
|
||||
end
|
||||
|
||||
it { is_expected.to be_retryable }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not retryable' do
|
||||
context 'when build is running' do
|
||||
before do
|
||||
build.run!
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_retryable }
|
||||
end
|
||||
|
||||
context 'when build is skipped' do
|
||||
before do
|
||||
build.skip!
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_retryable }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1180,4 +1246,13 @@ describe Ci::Build, models: true do
|
|||
it { is_expected.to eq('review/master') }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'returns a detailed status' do
|
||||
expect(build.detailed_status(user))
|
||||
.to be_a Gitlab::Ci::Status::Build::Cancelable
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -442,11 +442,15 @@ describe Ci::Pipeline, models: true do
|
|||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
subject { pipeline.detailed_status(user) }
|
||||
|
||||
context 'when pipeline is created' do
|
||||
let(:pipeline) { create(:ci_pipeline, status: :created) }
|
||||
|
||||
it 'returns detailed status for created pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'created'
|
||||
expect(subject.text).to eq 'created'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -454,7 +458,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :pending) }
|
||||
|
||||
it 'returns detailed status for pending pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'pending'
|
||||
expect(subject.text).to eq 'pending'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -462,7 +466,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :running) }
|
||||
|
||||
it 'returns detailed status for running pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'running'
|
||||
expect(subject.text).to eq 'running'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -470,7 +474,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :success) }
|
||||
|
||||
it 'returns detailed status for successful pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'passed'
|
||||
expect(subject.text).to eq 'passed'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -478,7 +482,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :failed) }
|
||||
|
||||
it 'returns detailed status for failed pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'failed'
|
||||
expect(subject.text).to eq 'failed'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -486,7 +490,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :canceled) }
|
||||
|
||||
it 'returns detailed status for canceled pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'canceled'
|
||||
expect(subject.text).to eq 'canceled'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -494,7 +498,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :skipped) }
|
||||
|
||||
it 'returns detailed status for skipped pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'skipped'
|
||||
expect(subject.text).to eq 'skipped'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -506,7 +510,7 @@ describe Ci::Pipeline, models: true do
|
|||
end
|
||||
|
||||
it 'retruns detailed status for successful pipeline with warnings' do
|
||||
expect(pipeline.detailed_status.label).to eq 'passed with warnings'
|
||||
expect(subject.label).to eq 'passed with warnings'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -68,7 +68,9 @@ describe Ci::Stage, models: true do
|
|||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
subject { stage.detailed_status }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
subject { stage.detailed_status(user) }
|
||||
|
||||
context 'when build is created' do
|
||||
let!(:stage_build) { create_job(:ci_build, status: :created) }
|
||||
|
|
|
@ -234,4 +234,13 @@ describe CommitStatus, models: true do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'returns a detailed status' do
|
||||
expect(commit_status.detailed_status(user))
|
||||
.to be_a Gitlab::Ci::Status::Success
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe GenericCommitStatus, models: true do
|
||||
let(:pipeline) { FactoryGirl.create :ci_pipeline }
|
||||
let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, pipeline: pipeline }
|
||||
let(:pipeline) { create(:ci_pipeline) }
|
||||
|
||||
let(:generic_commit_status) do
|
||||
create(:generic_commit_status, pipeline: pipeline)
|
||||
end
|
||||
|
||||
describe '#context' do
|
||||
subject { generic_commit_status.context }
|
||||
|
@ -17,6 +20,15 @@ describe GenericCommitStatus, models: true do
|
|||
it { is_expected.to eq([:external]) }
|
||||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'returns detailed status object' do
|
||||
expect(generic_commit_status.detailed_status(user))
|
||||
.to be_a Gitlab::Ci::Status::Success
|
||||
end
|
||||
end
|
||||
|
||||
describe 'set_default_values' do
|
||||
before do
|
||||
generic_commit_status.context = nil
|
||||
|
|
Loading…
Reference in a new issue