summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-08-15 23:29:07 +0200
committerKamil Trzcinski <ayufan@ayufan.eu>2016-08-15 23:29:07 +0200
commit8de2f5b103f84a76ff941a80ac7fc0bb934b480f (patch)
tree810cb183f99593ebb964feca90a1f6051bf70617
parentd626c1d3729f500a891a6934ea779136671ef8b2 (diff)
parente8aab1cd1550dd14408ae4c7b51f45110898b949 (diff)
downloadgitlab-ce-8de2f5b103f84a76ff941a80ac7fc0bb934b480f.tar.gz
Merge branch 'fix-failing-tests' into pipeline-hooks-without-slack
-rw-r--r--CHANGELOG1
-rw-r--r--app/controllers/projects/badges_controller.rb17
-rw-r--r--app/controllers/projects/pipelines_settings_controller.rb8
-rw-r--r--app/views/projects/pipelines_settings/_badge.html.haml27
-rw-r--r--app/views/projects/pipelines_settings/show.html.haml25
-rw-r--r--config/routes.rb5
-rw-r--r--db/fixtures/development/14_builds.rb59
-rw-r--r--doc/ci/pipelines.md35
-rw-r--r--doc/ci/quick_start/README.md12
-rw-r--r--lib/gitlab/badge/base.rb21
-rw-r--r--lib/gitlab/badge/build.rb30
-rw-r--r--lib/gitlab/badge/build/metadata.rb22
-rw-r--r--lib/gitlab/badge/build/status.rb37
-rw-r--r--lib/gitlab/badge/build/template.rb32
-rw-r--r--lib/gitlab/badge/coverage/metadata.rb30
-rw-r--r--lib/gitlab/badge/coverage/report.rb56
-rw-r--r--lib/gitlab/badge/coverage/template.rb52
-rw-r--r--lib/gitlab/badge/metadata.rb36
-rw-r--r--lib/gitlab/badge/template.rb49
-rw-r--r--spec/controllers/admin/groups_controller_spec.rb5
-rw-r--r--spec/controllers/groups_controller_spec.rb5
-rw-r--r--spec/features/projects/badges/coverage_spec.rb73
-rw-r--r--spec/features/projects/badges/list_spec.rb46
-rw-r--r--spec/lib/gitlab/badge/build/metadata_spec.rb36
-rw-r--r--spec/lib/gitlab/badge/build/status_spec.rb (renamed from spec/lib/gitlab/badge/build_spec.rb)38
-rw-r--r--spec/lib/gitlab/badge/build/template_spec.rb22
-rw-r--r--spec/lib/gitlab/badge/coverage/metadata_spec.rb30
-rw-r--r--spec/lib/gitlab/badge/coverage/report_spec.rb93
-rw-r--r--spec/lib/gitlab/badge/coverage/template_spec.rb130
-rw-r--r--spec/lib/gitlab/badge/shared/metadata.rb21
-rw-r--r--spec/models/project_services/irker_service_spec.rb21
31 files changed, 853 insertions, 221 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 47cae4909e9..5218f04a5a1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
Please view this file on the master branch, on stable branches it's out of date.
v 8.11.0 (unreleased)
+ - Add test coverage report badge. !5708
- Remove the http_parser.rb dependency by removing the tinder gem. !5758 (tbalthazar)
- Ability to specify branches for Pivotal Tracker integration (Egor Lynko)
- Fix don't pass a local variable called `i` to a partial. !20510 (herminiotorres)
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index d0f5071d2cc..6c25cd83a24 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -4,11 +4,24 @@ class Projects::BadgesController < Projects::ApplicationController
before_action :no_cache_headers, except: [:index]
def build
- badge = Gitlab::Badge::Build.new(project, params[:ref])
+ build_status = Gitlab::Badge::Build::Status
+ .new(project, params[:ref])
+ render_badge build_status
+ end
+
+ def coverage
+ coverage_report = Gitlab::Badge::Coverage::Report
+ .new(project, params[:ref], params[:job])
+
+ render_badge coverage_report
+ end
+
+ private
+
+ def render_badge(badge)
respond_to do |format|
format.html { render_404 }
-
format.svg do
render 'badge', locals: { badge: badge.template }
end
diff --git a/app/controllers/projects/pipelines_settings_controller.rb b/app/controllers/projects/pipelines_settings_controller.rb
index 75dd3648e45..9136633b87a 100644
--- a/app/controllers/projects/pipelines_settings_controller.rb
+++ b/app/controllers/projects/pipelines_settings_controller.rb
@@ -3,7 +3,13 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController
def show
@ref = params[:ref] || @project.default_branch || 'master'
- @build_badge = Gitlab::Badge::Build.new(@project, @ref).metadata
+
+ @badges = [Gitlab::Badge::Build::Status,
+ Gitlab::Badge::Coverage::Report]
+
+ @badges.map! do |badge|
+ badge.new(@project, @ref).metadata
+ end
end
def update
diff --git a/app/views/projects/pipelines_settings/_badge.html.haml b/app/views/projects/pipelines_settings/_badge.html.haml
new file mode 100644
index 00000000000..7b7fa56d993
--- /dev/null
+++ b/app/views/projects/pipelines_settings/_badge.html.haml
@@ -0,0 +1,27 @@
+.row{ class: badge.title.gsub(' ', '-') }
+ .col-lg-3.profile-settings-sidebar
+ %h4.prepend-top-0
+ = badge.title.capitalize
+ .col-lg-9
+ .prepend-top-10
+ .panel.panel-default
+ .panel-heading
+ %b
+ = badge.title.capitalize
+ &middot;
+ = badge.to_html
+ .pull-right
+ = render 'shared/ref_switcher', destination: 'badges', align_right: true
+ .panel-body
+ .row
+ .col-md-2.text-center
+ Markdown
+ .col-md-10.code.js-syntax-highlight
+ = highlight('.md', badge.to_markdown)
+ .row
+ %hr
+ .row
+ .col-md-2.text-center
+ HTML
+ .col-md-10.code.js-syntax-highlight
+ = highlight('.html', badge.to_html)
diff --git a/app/views/projects/pipelines_settings/show.html.haml b/app/views/projects/pipelines_settings/show.html.haml
index 228bad36ebd..8c7222bfe3d 100644
--- a/app/views/projects/pipelines_settings/show.html.haml
+++ b/app/views/projects/pipelines_settings/show.html.haml
@@ -77,27 +77,4 @@
%hr
.row.prepend-top-default
- .col-lg-3.profile-settings-sidebar
- %h4.prepend-top-0
- Builds Badge
- .col-lg-9
- .prepend-top-10
- .panel.panel-default
- .panel-heading
- %b Builds badge &middot;
- = @build_badge.to_html
- .pull-right
- = render 'shared/ref_switcher', destination: 'badges', align_right: true
- .panel-body
- .row
- .col-md-2.text-center
- Markdown
- .col-md-10.code.js-syntax-highlight
- = highlight('.md', @build_badge.to_markdown)
- .row
- %hr
- .row
- .col-md-2.text-center
- HTML
- .col-md-10.code.js-syntax-highlight
- = highlight('.html', @build_badge.to_html)
+ = render partial: 'badge', collection: @badges
diff --git a/config/routes.rb b/config/routes.rb
index 9a98fab15a3..cf6773917cf 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -869,7 +869,10 @@ Rails.application.routes.draw do
resources :badges, only: [:index] do
collection do
scope '*ref', constraints: { ref: Gitlab::Regex.git_reference_regex } do
- get :build, constraints: { format: /svg/ }
+ constraints format: /svg/ do
+ get :build
+ get :coverage
+ end
end
end
end
diff --git a/db/fixtures/development/14_builds.rb b/db/fixtures/development/14_builds.rb
index e65abe4ef77..6441a036e75 100644
--- a/db/fixtures/development/14_builds.rb
+++ b/db/fixtures/development/14_builds.rb
@@ -1,5 +1,21 @@
class Gitlab::Seeder::Builds
STAGES = %w[build notify_build test notify_test deploy notify_deploy]
+ BUILDS = [
+ { name: 'build:linux', stage: 'build', status: :success },
+ { name: 'build:osx', stage: 'build', status: :success },
+ { name: 'slack post build', stage: 'notify_build', status: :success },
+ { name: 'rspec:linux', stage: 'test', status: :success },
+ { name: 'rspec:windows', stage: 'test', status: :success },
+ { name: 'rspec:windows', stage: 'test', status: :success },
+ { name: 'rspec:osx', stage: 'test', status_event: :success },
+ { name: 'spinach:linux', stage: 'test', status: :pending },
+ { name: 'spinach:osx', stage: 'test', status: :canceled },
+ { name: 'cucumber:linux', stage: 'test', status: :running },
+ { name: 'cucumber:osx', stage: 'test', status: :failed },
+ { name: 'slack post test', stage: 'notify_test', status: :success },
+ { name: 'staging', stage: 'deploy', environment: 'staging', status: :success },
+ { name: 'production', stage: 'deploy', environment: 'production', when: 'manual', status: :success },
+ ]
def initialize(project)
@project = project
@@ -8,25 +24,7 @@ class Gitlab::Seeder::Builds
def seed!
pipelines.each do |pipeline|
begin
- build_create!(pipeline, name: 'build:linux', stage: 'build', status_event: :success)
- build_create!(pipeline, name: 'build:osx', stage: 'build', status_event: :success)
-
- build_create!(pipeline, name: 'slack post build', stage: 'notify_build', status_event: :success)
-
- build_create!(pipeline, name: 'rspec:linux', stage: 'test', status_event: :success)
- build_create!(pipeline, name: 'rspec:windows', stage: 'test', status_event: :success)
- build_create!(pipeline, name: 'rspec:windows', stage: 'test', status_event: :success)
- build_create!(pipeline, name: 'rspec:osx', stage: 'test', status_event: :success)
- build_create!(pipeline, name: 'spinach:linux', stage: 'test', status: :pending)
- build_create!(pipeline, name: 'spinach:osx', stage: 'test', status_event: :cancel)
- build_create!(pipeline, name: 'cucumber:linux', stage: 'test', status_event: :run)
- build_create!(pipeline, name: 'cucumber:osx', stage: 'test', status_event: :drop)
-
- build_create!(pipeline, name: 'slack post test', stage: 'notify_test', status_event: :success)
-
- build_create!(pipeline, name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success)
- build_create!(pipeline, name: 'production', stage: 'deploy', environment: 'production', when: 'manual', status: :success)
-
+ BUILDS.each { |opts| build_create!(pipeline, opts) }
commit_status_create!(pipeline, name: 'jenkins', status: :success)
print '.'
@@ -48,21 +46,22 @@ class Gitlab::Seeder::Builds
def build_create!(pipeline, opts = {})
attributes = build_attributes_for(pipeline, opts)
- build = Ci::Build.create!(attributes)
- if opts[:name].start_with?('build')
- artifacts_cache_file(artifacts_archive_path) do |file|
- build.artifacts_file = file
- end
+ Ci::Build.create!(attributes) do |build|
+ if opts[:name].start_with?('build')
+ artifacts_cache_file(artifacts_archive_path) do |file|
+ build.artifacts_file = file
+ end
- artifacts_cache_file(artifacts_metadata_path) do |file|
- build.artifacts_metadata = file
+ artifacts_cache_file(artifacts_metadata_path) do |file|
+ build.artifacts_metadata = file
+ end
end
- end
- if %w(running success failed).include?(build.status)
- # We need to set build trace after saving a build (id required)
- build.trace = FFaker::Lorem.paragraphs(6).join("\n\n")
+ if %w(running success failed).include?(build.status)
+ # We need to set build trace after saving a build (id required)
+ build.trace = FFaker::Lorem.paragraphs(6).join("\n\n")
+ end
end
end
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index 48a9f994759..d90d7aca4fd 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -32,6 +32,41 @@ project.
Clicking on a pipeline will show the builds that were run for that pipeline.
+## Badges
+
+There are build status and test coverage report badges available.
+
+Go to pipeline settings to see available badges and code you can use to embed
+badges in the `README.md` or your website.
+
+### Build status badge
+
+You can access a build status badge image using following link:
+
+```
+http://example.gitlab.com/namespace/project/badges/branch/build.svg
+```
+
+### Test coverage report badge
+
+GitLab makes it possible to define the regular expression for coverage report,
+that each build log will be matched against. This means that each build in the
+pipeline can have the test coverage percentage value defined.
+
+You can access test coverage badge using following link:
+
+```
+http://example.gitlab.com/namespace/project/badges/branch/coverage.svg
+```
+
+If you would like to get the coverage report from the specific job, you can add
+a `job=coverage_job_name` parameter to the URL. For example, it is possible to
+use following Markdown code to embed the est coverage report into `README.md`:
+
+```markdown
+![coverage](http://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)
+```
+
[builds]: #builds
[jobs]: yaml/README.md#jobs
[stages]: yaml/README.md#stages
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 6a3c416d995..c835ebc2d44 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -218,21 +218,13 @@ project's settings.
For more information read the
[Builds emails service documentation](../../project_services/builds_emails.md).
-## Builds badge
-
-You can access a builds badge image using following link:
-
-```
-http://example.gitlab.com/namespace/project/badges/branch/build.svg
-```
-
-Awesome! You started using CI in GitLab!
-
## Examples
Visit the [examples README][examples] to see a list of examples using GitLab
CI with various languages.
+Awesome! You started using CI in GitLab!
+
[runner-install]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/tree/master#install-gitlab-runner
[blog-ci]: https://about.gitlab.com/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/
[examples]: ../examples/README.md
diff --git a/lib/gitlab/badge/base.rb b/lib/gitlab/badge/base.rb
new file mode 100644
index 00000000000..909fa24fa90
--- /dev/null
+++ b/lib/gitlab/badge/base.rb
@@ -0,0 +1,21 @@
+module Gitlab
+ module Badge
+ class Base
+ def entity
+ raise NotImplementedError
+ end
+
+ def status
+ raise NotImplementedError
+ end
+
+ def metadata
+ raise NotImplementedError
+ end
+
+ def template
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/build.rb b/lib/gitlab/badge/build.rb
deleted file mode 100644
index 1de721a2269..00000000000
--- a/lib/gitlab/badge/build.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-module Gitlab
- module Badge
- ##
- # Build badge
- #
- class Build
- delegate :key_text, :value_text, to: :template
-
- def initialize(project, ref)
- @project = project
- @ref = ref
- @sha = @project.commit(@ref).try(:sha)
- end
-
- def status
- @project.pipelines
- .where(sha: @sha, ref: @ref)
- .status || 'unknown'
- end
-
- def metadata
- @metadata ||= Build::Metadata.new(@project, @ref)
- end
-
- def template
- @template ||= Build::Template.new(status)
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/build/metadata.rb b/lib/gitlab/badge/build/metadata.rb
index 553ef8d7b16..f87a7b7942e 100644
--- a/lib/gitlab/badge/build/metadata.rb
+++ b/lib/gitlab/badge/build/metadata.rb
@@ -1,25 +1,17 @@
module Gitlab
module Badge
- class Build
+ module Build
##
# Class that describes build badge metadata
#
- class Metadata
- include Gitlab::Application.routes.url_helpers
- include ActionView::Helpers::AssetTagHelper
- include ActionView::Helpers::UrlHelper
-
- def initialize(project, ref)
- @project = project
- @ref = ref
- end
-
- def to_html
- link_to(image_tag(image_url, alt: 'build status'), link_url)
+ class Metadata < Badge::Metadata
+ def initialize(badge)
+ @project = badge.project
+ @ref = badge.ref
end
- def to_markdown
- "[![build status](#{image_url})](#{link_url})"
+ def title
+ 'build status'
end
def image_url
diff --git a/lib/gitlab/badge/build/status.rb b/lib/gitlab/badge/build/status.rb
new file mode 100644
index 00000000000..50aa45e5406
--- /dev/null
+++ b/lib/gitlab/badge/build/status.rb
@@ -0,0 +1,37 @@
+module Gitlab
+ module Badge
+ module Build
+ ##
+ # Build status badge
+ #
+ class Status < Badge::Base
+ attr_reader :project, :ref
+
+ def initialize(project, ref)
+ @project = project
+ @ref = ref
+
+ @sha = @project.commit(@ref).try(:sha)
+ end
+
+ def entity
+ 'build'
+ end
+
+ def status
+ @project.pipelines
+ .where(sha: @sha, ref: @ref)
+ .status || 'unknown'
+ end
+
+ def metadata
+ @metadata ||= Build::Metadata.new(self)
+ end
+
+ def template
+ @template ||= Build::Template.new(self)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/build/template.rb b/lib/gitlab/badge/build/template.rb
index deba3b669b3..2b95ddfcb53 100644
--- a/lib/gitlab/badge/build/template.rb
+++ b/lib/gitlab/badge/build/template.rb
@@ -1,12 +1,12 @@
module Gitlab
module Badge
- class Build
+ module Build
##
# Class that represents a build badge template.
#
# Template object will be passed to badge.svg.erb template.
#
- class Template
+ class Template < Badge::Template
STATUS_COLOR = {
success: '#4c1',
failed: '#e05d44',
@@ -17,16 +17,17 @@ module Gitlab
unknown: '#9f9f9f'
}
- def initialize(status)
- @status = status
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
end
def key_text
- 'build'
+ @entity.to_s
end
def value_text
- @status
+ @status.to_s
end
def key_width
@@ -37,25 +38,8 @@ module Gitlab
54
end
- def key_color
- '#555'
- end
-
def value_color
- STATUS_COLOR[@status.to_sym] ||
- STATUS_COLOR[:unknown]
- end
-
- def key_text_anchor
- key_width / 2
- end
-
- def value_text_anchor
- key_width + (value_width / 2)
- end
-
- def width
- key_width + value_width
+ STATUS_COLOR[@status.to_sym] || STATUS_COLOR[:unknown]
end
end
end
diff --git a/lib/gitlab/badge/coverage/metadata.rb b/lib/gitlab/badge/coverage/metadata.rb
new file mode 100644
index 00000000000..53588185622
--- /dev/null
+++ b/lib/gitlab/badge/coverage/metadata.rb
@@ -0,0 +1,30 @@
+module Gitlab
+ module Badge
+ module Coverage
+ ##
+ # Class that describes coverage badge metadata
+ #
+ class Metadata < Badge::Metadata
+ def initialize(badge)
+ @project = badge.project
+ @ref = badge.ref
+ @job = badge.job
+ end
+
+ def title
+ 'coverage report'
+ end
+
+ def image_url
+ coverage_namespace_project_badges_url(@project.namespace,
+ @project, @ref,
+ format: :svg)
+ end
+
+ def link_url
+ namespace_project_commits_url(@project.namespace, @project, id: @ref)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/coverage/report.rb b/lib/gitlab/badge/coverage/report.rb
new file mode 100644
index 00000000000..3d56ea3e47a
--- /dev/null
+++ b/lib/gitlab/badge/coverage/report.rb
@@ -0,0 +1,56 @@
+module Gitlab
+ module Badge
+ module Coverage
+ ##
+ # Test coverage report badge
+ #
+ class Report < Badge::Base
+ attr_reader :project, :ref, :job
+
+ def initialize(project, ref, job = nil)
+ @project = project
+ @ref = ref
+ @job = job
+
+ @pipeline = @project.pipelines
+ .where(ref: @ref)
+ .where(sha: @project.commit(@ref).try(:sha))
+ .first
+ end
+
+ def entity
+ 'coverage'
+ end
+
+ def status
+ @coverage ||= raw_coverage
+ return unless @coverage
+
+ @coverage.to_i
+ end
+
+ def metadata
+ @metadata ||= Coverage::Metadata.new(self)
+ end
+
+ def template
+ @template ||= Coverage::Template.new(self)
+ end
+
+ private
+
+ def raw_coverage
+ return unless @pipeline
+
+ if @job.blank?
+ @pipeline.coverage
+ else
+ @pipeline.builds
+ .find_by(name: @job)
+ .try(:coverage)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/coverage/template.rb b/lib/gitlab/badge/coverage/template.rb
new file mode 100644
index 00000000000..06e0d084e9f
--- /dev/null
+++ b/lib/gitlab/badge/coverage/template.rb
@@ -0,0 +1,52 @@
+module Gitlab
+ module Badge
+ module Coverage
+ ##
+ # Class that represents a coverage badge template.
+ #
+ # Template object will be passed to badge.svg.erb template.
+ #
+ class Template < Badge::Template
+ STATUS_COLOR = {
+ good: '#4c1',
+ acceptable: '#a3c51c',
+ medium: '#dfb317',
+ low: '#e05d44',
+ unknown: '#9f9f9f'
+ }
+
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
+ end
+
+ def key_text
+ @entity.to_s
+ end
+
+ def value_text
+ @status ? "#{@status}%" : 'unknown'
+ end
+
+ def key_width
+ 62
+ end
+
+ def value_width
+ @status ? 36 : 58
+ end
+
+ def value_color
+ case @status
+ when 95..100 then STATUS_COLOR[:good]
+ when 90..95 then STATUS_COLOR[:acceptable]
+ when 75..90 then STATUS_COLOR[:medium]
+ when 0..75 then STATUS_COLOR[:low]
+ else
+ STATUS_COLOR[:unknown]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/metadata.rb b/lib/gitlab/badge/metadata.rb
new file mode 100644
index 00000000000..548f85b78bb
--- /dev/null
+++ b/lib/gitlab/badge/metadata.rb
@@ -0,0 +1,36 @@
+module Gitlab
+ module Badge
+ ##
+ # Abstract class for badge metadata
+ #
+ class Metadata
+ include Gitlab::Application.routes.url_helpers
+ include ActionView::Helpers::AssetTagHelper
+ include ActionView::Helpers::UrlHelper
+
+ def initialize(badge)
+ @badge = badge
+ end
+
+ def to_html
+ link_to(image_tag(image_url, alt: title), link_url)
+ end
+
+ def to_markdown
+ "[![#{title}](#{image_url})](#{link_url})"
+ end
+
+ def title
+ raise NotImplementedError
+ end
+
+ def image_url
+ raise NotImplementedError
+ end
+
+ def link_url
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/badge/template.rb b/lib/gitlab/badge/template.rb
new file mode 100644
index 00000000000..bfeb0052642
--- /dev/null
+++ b/lib/gitlab/badge/template.rb
@@ -0,0 +1,49 @@
+module Gitlab
+ module Badge
+ ##
+ # Abstract template class for badges
+ #
+ class Template
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
+ end
+
+ def key_text
+ raise NotImplementedError
+ end
+
+ def value_text
+ raise NotImplementedError
+ end
+
+ def key_width
+ raise NotImplementedError
+ end
+
+ def value_width
+ raise NotImplementedError
+ end
+
+ def value_color
+ raise NotImplementedError
+ end
+
+ def key_color
+ '#555'
+ end
+
+ def key_text_anchor
+ key_width / 2
+ end
+
+ def value_text_anchor
+ key_width + (value_width / 2)
+ end
+
+ def width
+ key_width + value_width
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb
index 0239aea47fb..602de72d23f 100644
--- a/spec/controllers/admin/groups_controller_spec.rb
+++ b/spec/controllers/admin/groups_controller_spec.rb
@@ -7,12 +7,13 @@ describe Admin::GroupsController do
before do
sign_in(admin)
- Sidekiq::Testing.fake!
end
describe 'DELETE #destroy' do
it 'schedules a group destroy' do
- expect { delete :destroy, id: project.group.path }.to change(GroupDestroyWorker.jobs, :size).by(1)
+ Sidekiq::Testing.fake! do
+ expect { delete :destroy, id: project.group.path }.to change(GroupDestroyWorker.jobs, :size).by(1)
+ end
end
it 'redirects to the admin group path' do
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 4ae6364207b..a763e2c5ba8 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -89,12 +89,13 @@ describe GroupsController do
context 'as the group owner' do
before do
- Sidekiq::Testing.fake!
sign_in(user)
end
it 'schedules a group destroy' do
- expect { delete :destroy, id: group.path }.to change(GroupDestroyWorker.jobs, :size).by(1)
+ Sidekiq::Testing.fake! do
+ expect { delete :destroy, id: group.path }.to change(GroupDestroyWorker.jobs, :size).by(1)
+ end
end
it 'redirects to the root path' do
diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb
new file mode 100644
index 00000000000..af86d3c338a
--- /dev/null
+++ b/spec/features/projects/badges/coverage_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+feature 'test coverage badge' do
+ given!(:user) { create(:user) }
+ given!(:project) { create(:project, :private) }
+
+ given!(:pipeline) do
+ create(:ci_pipeline, project: project,
+ ref: 'master',
+ sha: project.commit.id)
+ end
+
+ context 'when user has access to view badge' do
+ background do
+ project.team << [user, :developer]
+ login_as(user)
+ end
+
+ scenario 'user requests coverage badge image for pipeline' do
+ create_job(coverage: 100, name: 'test:1')
+ create_job(coverage: 90, name: 'test:2')
+
+ show_test_coverage_badge
+
+ expect_coverage_badge('95%')
+ end
+
+ scenario 'user requests coverage badge for specific job' do
+ create_job(coverage: 50, name: 'test:1')
+ create_job(coverage: 50, name: 'test:2')
+ create_job(coverage: 85, name: 'coverage')
+
+ show_test_coverage_badge(job: 'coverage')
+
+ expect_coverage_badge('85%')
+ end
+
+ scenario 'user requests coverage badge for pipeline without coverage' do
+ create_job(coverage: nil, name: 'test')
+
+ show_test_coverage_badge
+
+ expect_coverage_badge('unknown')
+ end
+ end
+
+ context 'when user does not have access to view badge' do
+ background { login_as(user) }
+
+ scenario 'user requests test coverage badge image' do
+ show_test_coverage_badge
+
+ expect(page).to have_http_status(404)
+ end
+ end
+
+ def create_job(coverage:, name:)
+ create(:ci_build, name: name,
+ coverage: coverage,
+ pipeline: pipeline)
+ end
+
+ def show_test_coverage_badge(job: nil)
+ visit coverage_namespace_project_badges_path(
+ project.namespace, project, ref: :master, job: job, format: :svg)
+ end
+
+ def expect_coverage_badge(coverage)
+ svg = Nokogiri::XML.parse(page.body)
+ expect(page.response_headers['Content-Type']).to include('image/svg+xml')
+ expect(svg.at(%Q{text:contains("#{coverage}")})).to be_truthy
+ end
+end
diff --git a/spec/features/projects/badges/list_spec.rb b/spec/features/projects/badges/list_spec.rb
index 75166bca119..67a4a5d1ab1 100644
--- a/spec/features/projects/badges/list_spec.rb
+++ b/spec/features/projects/badges/list_spec.rb
@@ -9,25 +9,43 @@ feature 'list of badges' do
visit namespace_project_pipelines_settings_path(project.namespace, project)
end
- scenario 'user displays list of badges' do
- expect(page).to have_content 'build status'
- expect(page).to have_content 'Markdown'
- expect(page).to have_content 'HTML'
- expect(page).to have_css('.highlight', count: 2)
- expect(page).to have_xpath("//img[@alt='build status']")
-
- page.within('.highlight', match: :first) do
- expect(page).to have_content 'badges/master/build.svg'
+ scenario 'user wants to see build status badge' do
+ page.within('.build-status') do
+ expect(page).to have_content 'build status'
+ expect(page).to have_content 'Markdown'
+ expect(page).to have_content 'HTML'
+ expect(page).to have_css('.highlight', count: 2)
+ expect(page).to have_xpath("//img[@alt='build status']")
+
+ page.within('.highlight', match: :first) do
+ expect(page).to have_content 'badges/master/build.svg'
+ end
end
end
- scenario 'user changes current ref on badges list page', js: true do
- first('.js-project-refs-dropdown').click
+ scenario 'user wants to see coverage report badge' do
+ page.within('.coverage-report') do
+ expect(page).to have_content 'coverage report'
+ expect(page).to have_content 'Markdown'
+ expect(page).to have_content 'HTML'
+ expect(page).to have_css('.highlight', count: 2)
+ expect(page).to have_xpath("//img[@alt='coverage report']")
- page.within '.project-refs-form' do
- click_link 'improve/awesome'
+ page.within('.highlight', match: :first) do
+ expect(page).to have_content 'badges/master/coverage.svg'
+ end
end
+ end
+
+ scenario 'user changes current ref of build status badge', js: true do
+ page.within('.build-status') do
+ first('.js-project-refs-dropdown').click
- expect(page).to have_content 'badges/improve/awesome/build.svg'
+ page.within '.project-refs-form' do
+ click_link 'improve/awesome'
+ end
+
+ expect(page).to have_content 'badges/improve/awesome/build.svg'
+ end
end
end
diff --git a/spec/lib/gitlab/badge/build/metadata_spec.rb b/spec/lib/gitlab/badge/build/metadata_spec.rb
index ad5388215c2..d678e522721 100644
--- a/spec/lib/gitlab/badge/build/metadata_spec.rb
+++ b/spec/lib/gitlab/badge/build/metadata_spec.rb
@@ -1,37 +1,27 @@
require 'spec_helper'
+require 'lib/gitlab/badge/shared/metadata'
describe Gitlab::Badge::Build::Metadata do
- let(:project) { create(:project) }
- let(:branch) { 'master' }
- let(:badge) { described_class.new(project, branch) }
+ let(:badge) { double(project: create(:project), ref: 'feature') }
+ let(:metadata) { described_class.new(badge) }
- describe '#to_html' do
- let(:html) { Nokogiri::HTML.parse(badge.to_html) }
- let(:a_href) { html.at('a') }
+ it_behaves_like 'badge metadata'
- it 'points to link' do
- expect(a_href[:href]).to eq badge.link_url
- end
-
- it 'contains clickable image' do
- expect(a_href.children.first.name).to eq 'img'
+ describe '#title' do
+ it 'returns build status title' do
+ expect(metadata.title).to eq 'build status'
end
end
- describe '#to_markdown' do
- subject { badge.to_markdown }
-
- it { is_expected.to include badge.image_url }
- it { is_expected.to include badge.link_url }
- end
-
describe '#image_url' do
- subject { badge.image_url }
- it { is_expected.to include "badges/#{branch}/build.svg" }
+ it 'returns valid url' do
+ expect(metadata.image_url).to include 'badges/feature/build.svg'
+ end
end
describe '#link_url' do
- subject { badge.link_url }
- it { is_expected.to include "commits/#{branch}" }
+ it 'returns valid link' do
+ expect(metadata.link_url).to include 'commits/feature'
+ end
end
end
diff --git a/spec/lib/gitlab/badge/build_spec.rb b/spec/lib/gitlab/badge/build/status_spec.rb
index bb8144d5122..38eebb2a176 100644
--- a/spec/lib/gitlab/badge/build_spec.rb
+++ b/spec/lib/gitlab/badge/build/status_spec.rb
@@ -1,11 +1,23 @@
require 'spec_helper'
-describe Gitlab::Badge::Build do
+describe Gitlab::Badge::Build::Status do
let(:project) { create(:project) }
let(:sha) { project.commit.sha }
let(:branch) { 'master' }
let(:badge) { described_class.new(project, branch) }
+ describe '#entity' do
+ it 'always says build' do
+ expect(badge.entity).to eq 'build'
+ end
+ end
+
+ describe '#template' do
+ it 'returns badge template' do
+ expect(badge.template.key_text).to eq 'build'
+ end
+ end
+
describe '#metadata' do
it 'returns badge metadata' do
expect(badge.metadata.image_url)
@@ -13,12 +25,6 @@ describe Gitlab::Badge::Build do
end
end
- describe '#key_text' do
- it 'always says build' do
- expect(badge.key_text).to eq 'build'
- end
- end
-
context 'build exists' do
let!(:build) { create_build(project, sha, branch) }
@@ -30,12 +36,6 @@ describe Gitlab::Badge::Build do
expect(badge.status).to eq 'success'
end
end
-
- describe '#value_text' do
- it 'returns correct value text' do
- expect(badge.value_text).to eq 'success'
- end
- end
end
context 'build failed' do
@@ -46,12 +46,6 @@ describe Gitlab::Badge::Build do
expect(badge.status).to eq 'failed'
end
end
-
- describe '#value_text' do
- it 'has correct value text' do
- expect(badge.value_text).to eq 'failed'
- end
- end
end
context 'when outdated pipeline for given ref exists' do
@@ -87,12 +81,6 @@ describe Gitlab::Badge::Build do
expect(badge.status).to eq 'unknown'
end
end
-
- describe '#value_text' do
- it 'has correct value text' do
- expect(badge.value_text).to eq 'unknown'
- end
- end
end
def create_build(project, sha, branch)
diff --git a/spec/lib/gitlab/badge/build/template_spec.rb b/spec/lib/gitlab/badge/build/template_spec.rb
index 86dead3c54e..a7e21fb8bb1 100644
--- a/spec/lib/gitlab/badge/build/template_spec.rb
+++ b/spec/lib/gitlab/badge/build/template_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
describe Gitlab::Badge::Build::Template do
- let(:status) { 'success' }
- let(:template) { described_class.new(status) }
+ let(:badge) { double(entity: 'build', status: 'success') }
+ let(:template) { described_class.new(badge) }
describe '#key_text' do
it 'is always says build' do
@@ -34,15 +34,15 @@ describe Gitlab::Badge::Build::Template do
describe '#value_color' do
context 'when status is success' do
- let(:status) { 'success' }
-
it 'has expected color' do
expect(template.value_color).to eq '#4c1'
end
end
context 'when status is failed' do
- let(:status) { 'failed' }
+ before do
+ allow(badge).to receive(:status).and_return('failed')
+ end
it 'has expected color' do
expect(template.value_color).to eq '#e05d44'
@@ -50,7 +50,9 @@ describe Gitlab::Badge::Build::Template do
end
context 'when status is running' do
- let(:status) { 'running' }
+ before do
+ allow(badge).to receive(:status).and_return('running')
+ end
it 'has expected color' do
expect(template.value_color).to eq '#dfb317'
@@ -58,7 +60,9 @@ describe Gitlab::Badge::Build::Template do
end
context 'when status is unknown' do
- let(:status) { 'unknown' }
+ before do
+ allow(badge).to receive(:status).and_return('unknown')
+ end
it 'has expected color' do
expect(template.value_color).to eq '#9f9f9f'
@@ -66,7 +70,9 @@ describe Gitlab::Badge::Build::Template do
end
context 'when status does not match any known statuses' do
- let(:status) { 'invalid status' }
+ before do
+ allow(badge).to receive(:status).and_return('invalid')
+ end
it 'has expected color' do
expect(template.value_color).to eq '#9f9f9f'
diff --git a/spec/lib/gitlab/badge/coverage/metadata_spec.rb b/spec/lib/gitlab/badge/coverage/metadata_spec.rb
new file mode 100644
index 00000000000..74eaf7eaf8b
--- /dev/null
+++ b/spec/lib/gitlab/badge/coverage/metadata_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+require 'lib/gitlab/badge/shared/metadata'
+
+describe Gitlab::Badge::Coverage::Metadata do
+ let(:badge) do
+ double(project: create(:project), ref: 'feature', job: 'test')
+ end
+
+ let(:metadata) { described_class.new(badge) }
+
+ it_behaves_like 'badge metadata'
+
+ describe '#title' do
+ it 'returns coverage report title' do
+ expect(metadata.title).to eq 'coverage report'
+ end
+ end
+
+ describe '#image_url' do
+ it 'returns valid url' do
+ expect(metadata.image_url).to include 'badges/feature/coverage.svg'
+ end
+ end
+
+ describe '#link_url' do
+ it 'returns valid link' do
+ expect(metadata.link_url).to include 'commits/feature'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/badge/coverage/report_spec.rb b/spec/lib/gitlab/badge/coverage/report_spec.rb
new file mode 100644
index 00000000000..1ff49602486
--- /dev/null
+++ b/spec/lib/gitlab/badge/coverage/report_spec.rb
@@ -0,0 +1,93 @@
+require 'spec_helper'
+
+describe Gitlab::Badge::Coverage::Report do
+ let(:project) { create(:project) }
+ let(:job_name) { nil }
+
+ let(:badge) do
+ described_class.new(project, 'master', job_name)
+ end
+
+ describe '#entity' do
+ it 'describes a coverage' do
+ expect(badge.entity).to eq 'coverage'
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns correct metadata' do
+ expect(badge.metadata.image_url).to include 'coverage.svg'
+ end
+ end
+
+ describe '#template' do
+ it 'returns correct template' do
+ expect(badge.template.key_text).to eq 'coverage'
+ end
+ end
+
+ shared_examples 'unknown coverage report' do
+ context 'particular job specified' do
+ let(:job_name) { '' }
+
+ it 'returns nil' do
+ expect(badge.status).to be_nil
+ end
+ end
+
+ context 'particular job not specified' do
+ let(:job_name) { nil }
+
+ it 'returns nil' do
+ expect(badge.status).to be_nil
+ end
+ end
+ end
+
+ context 'pipeline exists' do
+ let!(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: project.commit.id,
+ ref: 'master')
+ end
+
+ context 'builds exist' do
+ before do
+ create(:ci_build, name: 'first', pipeline: pipeline, coverage: 40)
+ create(:ci_build, pipeline: pipeline, coverage: 60)
+ end
+
+ context 'particular job specified' do
+ let(:job_name) { 'first' }
+
+ it 'returns coverage for the particular job' do
+ expect(badge.status).to eq 40
+ end
+ end
+
+ context 'particular job not specified' do
+ let(:job_name) { '' }
+
+ it 'returns arithemetic mean for the pipeline' do
+ expect(badge.status).to eq 50
+ end
+ end
+ end
+
+ context 'builds do not exist' do
+ it_behaves_like 'unknown coverage report'
+
+ context 'particular job specified' do
+ let(:job_name) { 'nonexistent' }
+
+ it 'retruns nil' do
+ expect(badge.status).to be_nil
+ end
+ end
+ end
+ end
+
+ context 'pipeline does not exist' do
+ it_behaves_like 'unknown coverage report'
+ end
+end
diff --git a/spec/lib/gitlab/badge/coverage/template_spec.rb b/spec/lib/gitlab/badge/coverage/template_spec.rb
new file mode 100644
index 00000000000..383bae6e087
--- /dev/null
+++ b/spec/lib/gitlab/badge/coverage/template_spec.rb
@@ -0,0 +1,130 @@
+require 'spec_helper'
+
+describe Gitlab::Badge::Coverage::Template do
+ let(:badge) { double(entity: 'coverage', status: 90) }
+ let(:template) { described_class.new(badge) }
+
+ describe '#key_text' do
+ it 'is always says coverage' do
+ expect(template.key_text).to eq 'coverage'
+ end
+ end
+
+ describe '#value_text' do
+ context 'when coverage is known' do
+ it 'returns coverage percentage' do
+ expect(template.value_text).to eq '90%'
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'returns string that says coverage is unknown' do
+ expect(template.value_text).to eq 'unknown'
+ end
+ end
+ end
+
+ describe '#key_width' do
+ it 'has a fixed key width' do
+ expect(template.key_width).to eq 62
+ end
+ end
+
+ describe '#value_width' do
+ context 'when coverage is known' do
+ it 'is narrower when coverage is known' do
+ expect(template.value_width).to eq 36
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'is wider when coverage is unknown to fit text' do
+ expect(template.value_width).to eq 58
+ end
+ end
+ end
+
+ describe '#key_color' do
+ it 'always has the same color' do
+ expect(template.key_color).to eq '#555'
+ end
+ end
+
+ describe '#value_color' do
+ context 'when coverage is good' do
+ before do
+ allow(badge).to receive(:status).and_return(98)
+ end
+
+ it 'is green' do
+ expect(template.value_color).to eq '#4c1'
+ end
+ end
+
+ context 'when coverage is acceptable' do
+ before do
+ allow(badge).to receive(:status).and_return(90)
+ end
+
+ it 'is green-orange' do
+ expect(template.value_color).to eq '#a3c51c'
+ end
+ end
+
+ context 'when coverage is medium' do
+ before do
+ allow(badge).to receive(:status).and_return(75)
+ end
+
+ it 'is orange-yellow' do
+ expect(template.value_color).to eq '#dfb317'
+ end
+ end
+
+ context 'when coverage is low' do
+ before do
+ allow(badge).to receive(:status).and_return(50)
+ end
+
+ it 'is red' do
+ expect(template.value_color).to eq '#e05d44'
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'is grey' do
+ expect(template.value_color).to eq '#9f9f9f'
+ end
+ end
+ end
+
+ describe '#width' do
+ context 'when coverage is known' do
+ it 'returns the key width plus value width' do
+ expect(template.width).to eq 98
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'returns key width plus wider value width' do
+ expect(template.width).to eq 120
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/badge/shared/metadata.rb b/spec/lib/gitlab/badge/shared/metadata.rb
new file mode 100644
index 00000000000..0cf18514251
--- /dev/null
+++ b/spec/lib/gitlab/badge/shared/metadata.rb
@@ -0,0 +1,21 @@
+shared_examples 'badge metadata' do
+ describe '#to_html' do
+ let(:html) { Nokogiri::HTML.parse(metadata.to_html) }
+ let(:a_href) { html.at('a') }
+
+ it 'points to link' do
+ expect(a_href[:href]).to eq metadata.link_url
+ end
+
+ it 'contains clickable image' do
+ expect(a_href.children.first.name).to eq 'img'
+ end
+ end
+
+ describe '#to_markdown' do
+ subject { metadata.to_markdown }
+
+ it { is_expected.to include metadata.image_url }
+ it { is_expected.to include metadata.link_url }
+ end
+end
diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb
index 3bed0e6093f..ec092297f4f 100644
--- a/spec/models/project_services/irker_service_spec.rb
+++ b/spec/models/project_services/irker_service_spec.rb
@@ -54,19 +54,20 @@ describe IrkerService, models: true do
let(:colorize_messages) { '1' }
before do
+ @irker_server = TCPServer.new 'localhost', 0
+
allow(irker).to receive_messages(
- active: true,
- project: project,
- project_id: project.id,
- service_hook: true,
- server_host: 'localhost',
- server_port: 6659,
- default_irc_uri: 'irc://chat.freenode.net/',
- recipients: recipients,
- colorize_messages: colorize_messages)
+ active: true,
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ server_host: @irker_server.addr[2],
+ server_port: @irker_server.addr[1],
+ default_irc_uri: 'irc://chat.freenode.net/',
+ recipients: recipients,
+ colorize_messages: colorize_messages)
irker.valid?
- @irker_server = TCPServer.new 'localhost', 6659
end
after do