Commit e4db1cf8 authored by Erick Bajao's avatar Erick Bajao

Implement endpoints for code coverage graph

Adds an endpoint that will be used by the daily code coverage graph.
parent ce45c835
......@@ -12,7 +12,8 @@ class Projects::Ci::DailyBuildGroupReportResultsController < Projects::Applicati
def index
respond_to do |format|
format.csv { send_data(render_csv(results), type: 'text/csv; charset=utf-8') }
format.csv { send_data(render_csv(report_results), type: 'text/csv; charset=utf-8') }
format.json { render json: render_json(report_results) }
end
end
......@@ -37,7 +38,11 @@ class Projects::Ci::DailyBuildGroupReportResultsController < Projects::Applicati
).render
end
def results
def render_json(collection)
Ci::DailyBuildGroupReportResultSerializer.new.represent(collection, param_type: param_type)
end
def report_results
Ci::DailyBuildGroupReportResultsFinder.new(finder_params).execute
end
......
......@@ -71,6 +71,11 @@ class Projects::GraphsController < Projects::ApplicationController
namespace_id: @project.namespace,
project_id: @project,
format: :csv
),
graph_api_path: namespace_project_ci_daily_build_group_report_results_path(
namespace_id: @project.namespace,
project_id: @project,
format: :json
)
}
end
......
......@@ -17,18 +17,22 @@ module Ci
return none unless can?(current_user, :read_build_report_results, project)
Ci::DailyBuildGroupReportResult.recent_results(
{
project_id: project,
ref_path: ref_path,
date: start_date..end_date
},
limit: @limit
query_params,
limit: limit
)
end
private
attr_reader :current_user, :project, :ref_path, :start_date, :end_date
attr_reader :current_user, :project, :ref_path, :start_date, :end_date, :limit
def query_params
{
project_id: project,
ref_path: ref_path,
date: start_date..end_date
}
end
def none
Ci::DailyBuildGroupReportResult.none
......
# frozen_string_literal: true
module Ci
class DailyBuildGroupReportResultEntity < Grape::Entity
expose :date
::Ci::DailyBuildGroupReportResult::PARAM_TYPES.each do |type|
expose type, if: lambda { |report_result, options| options[:param_type] == type } do |report_result, options|
report_result.data[options[:param_type]]
end
end
end
end
# frozen_string_literal: true
module Ci
class DailyBuildGroupReportResultSerializer < BaseSerializer
entity ::Ci::DailyBuildGroupReportResultEntity
def represent(resource, opts = {})
group(resource).map do |group_name, data|
{
group_name: group_name,
data: super(data, opts)
}
end
end
private
def group(resource)
collect(resource).group_by(&:group_name)
end
def collect(resource)
return resource if resource.respond_to?(:group_by)
[resource]
end
end
end
......@@ -67,7 +67,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
namespace :ci do
resource :lint, only: [:show, :create]
resources :daily_build_group_report_results, only: [:index], constraints: { format: 'csv' }
resources :daily_build_group_report_results, only: [:index], constraints: { format: /(csv|json)/ }
end
namespace :settings do
......
......@@ -14,9 +14,10 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
before do
create_daily_coverage('rspec', 79.0, '2020-03-09')
create_daily_coverage('rspec', 77.0, '2020-03-08')
create_daily_coverage('karma', 81.0, '2019-12-10')
create_daily_coverage('rspec', 67.0, '2019-12-09')
create_daily_coverage('karma', 71.0, '2019-12-09')
create_daily_coverage('minitest', 67.0, '2019-12-09')
create_daily_coverage('mocha', 71.0, '2019-12-09')
sign_in(user)
......@@ -30,10 +31,33 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
param_type: param_type,
start_date: start_date,
end_date: end_date,
format: :csv
format: format
}
end
shared_examples_for 'validating param_type' do
context 'when given param_type is invalid' do
let(:param_type) { 'something_else' }
it 'responds with 422 error' do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
end
shared_examples_for 'ensuring policy' do
context 'when user is not allowed to read build report results' do
let(:allowed_to_read) { false }
it 'responds with 404 error' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
context 'when format is CSV' do
let(:format) { :csv }
it 'serves the results in CSV' do
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['Content-Type']).to eq('text/csv; charset=utf-8')
......@@ -41,6 +65,7 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
expect(csv_response).to eq([
%w[date group_name coverage],
['2020-03-09', 'rspec', '79.0'],
['2020-03-08', 'rspec', '77.0'],
['2019-12-10', 'karma', '81.0']
])
end
......@@ -50,32 +75,68 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
let(:end_date) { '2020-03-09' }
it 'limits the result to 90 days from the given start_date' do
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['Content-Type']).to eq('text/csv; charset=utf-8')
expect(csv_response).to eq([
%w[date group_name coverage],
['2020-03-09', 'rspec', '79.0'],
['2020-03-08', 'rspec', '77.0'],
['2019-12-10', 'karma', '81.0']
])
end
end
context 'when given param_type is invalid' do
let(:param_type) { 'something_else' }
it 'responds with 422 error' do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
it_behaves_like 'validating param_type'
it_behaves_like 'ensuring policy'
end
context 'when format is JSON' do
let(:format) { :json }
it 'serves the results in JSON' do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq([
{
'group_name' => 'rspec',
'data' => [
{ 'date' => '2020-03-09', 'coverage' => 79.0 },
{ 'date' => '2020-03-08', 'coverage' => 77.0 }
]
},
{
'group_name' => 'karma',
'data' => [
{ 'date' => '2019-12-10', 'coverage' => 81.0 }
]
}
])
end
context 'when user is not allowed to read build report results' do
let(:allowed_to_read) { false }
context 'when given date range spans more than 90 days' do
let(:start_date) { '2019-12-09' }
let(:end_date) { '2020-03-09' }
it 'responds with 404 error' do
expect(response).to have_gitlab_http_status(:not_found)
it 'limits the result to 90 days from the given start_date' do
expect(json_response).to eq([
{
'group_name' => 'rspec',
'data' => [
{ 'date' => '2020-03-09', 'coverage' => 79.0 },
{ 'date' => '2020-03-08', 'coverage' => 77.0 }
]
},
{
'group_name' => 'karma',
'data' => [
{ 'date' => '2019-12-10', 'coverage' => 81.0 }
]
}
])
end
end
it_behaves_like 'validating param_type'
it_behaves_like 'ensuring policy'
end
end
def create_daily_coverage(group_name, coverage, date)
......
......@@ -49,8 +49,8 @@ RSpec.describe Projects::GraphsController do
expect(assigns[:daily_coverage_options]).to eq(
base_params: {
start_date: Time.current.to_date - 90.days,
end_date: Time.current.to_date,
start_date: Date.current - 90.days,
end_date: Date.current,
ref_path: project.repository.expand_ref('master'),
param_type: 'coverage'
},
......@@ -58,6 +58,11 @@ RSpec.describe Projects::GraphsController do
namespace_id: project.namespace,
project_id: project,
format: :csv
),
graph_api_path: namespace_project_ci_daily_build_group_report_results_path(
namespace_id: project.namespace,
project_id: project,
format: :json
)
)
end
......
# frozen_string_literal: true
require 'spec_helper'
describe Ci::DailyBuildGroupReportResultEntity do
let(:report_result) { double(date: '2020-05-20', group_name: 'rspec', data: { 'coverage' => 79.1 }) }
let(:entity) { described_class.new(report_result, param_type: param_type) }
let(:param_type) { 'coverage' }
describe '#as_json' do
subject { entity.as_json }
it { is_expected.to include(:date) }
it { is_expected.not_to include(:group_name) }
it { is_expected.to include(:coverage) }
context 'when given param_type is not allowed' do
let(:param_type) { 'something_else' }
it { is_expected.not_to include(:coverage) }
it { is_expected.not_to include(:something_else) }
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Ci::DailyBuildGroupReportResultSerializer do
let(:report_result) do
[
double(date: '2020-05-20', group_name: 'rspec', data: { 'coverage' => 79.1 }),
double(date: '2020-05-20', group_name: 'karma', data: { 'coverage' => 90.1 }),
double(date: '2020-05-19', group_name: 'rspec', data: { 'coverage' => 77.1 }),
double(date: '2020-05-19', group_name: 'karma', data: { 'coverage' => 89.1 })
]
end
let(:serializer) { described_class.new.represent(report_result, param_type: 'coverage') }
describe '#to_json' do
let(:json) { Gitlab::Json.parse(serializer.to_json) }
it 'returns an array of group results' do
expect(json).to eq([
{
'group_name' => 'rspec',
'data' => [
{ 'date' => '2020-05-20', 'coverage' => 79.1 },
{ 'date' => '2020-05-19', 'coverage' => 77.1 }
]
},
{
'group_name' => 'karma',
'data' => [
{ 'date' => '2020-05-20', 'coverage' => 90.1 },
{ 'date' => '2020-05-19', 'coverage' => 89.1 }
]
}
])
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment