Commit 2d9371ae authored by Ezekiel Kigbo's avatar Ezekiel Kigbo Committed by Mark Florian

Added some additional specs to check filters

Adds additional feature specs to ensure
filters are applied correctly

Minor refactor specs
parent ec30dcea
...@@ -43,7 +43,7 @@ export default { ...@@ -43,7 +43,7 @@ export default {
<template> <template>
<chart-skeleton-loader v-if="isLoading" size="md" class="gl-my-4 gl-py-4" /> <chart-skeleton-loader v-if="isLoading" size="md" class="gl-my-4 gl-py-4" />
<div v-else class="gl-display-flex gl-flex-direction-column"> <div v-else class="gl-display-flex gl-flex-direction-column" data-testid="vsa-duration-chart">
<h4 class="gl-mt-0">{{ s__('CycleAnalytics|Days to completion') }}</h4> <h4 class="gl-mt-0">{{ s__('CycleAnalytics|Days to completion') }}</h4>
<stage-dropdown-filter <stage-dropdown-filter
v-if="stages.length" v-if="stages.length"
...@@ -58,7 +58,7 @@ export default { ...@@ -58,7 +58,7 @@ export default {
:tooltip-date-format="$options.durationChartTooltipDateFormat" :tooltip-date-format="$options.durationChartTooltipDateFormat"
:scatter-data="durationChartPlottableData" :scatter-data="durationChartPlottableData"
/> />
<div v-else ref="duration-chart-no-data" class="bs-callout bs-callout-info"> <div v-else class="bs-callout bs-callout-info">
{{ error }} {{ error }}
</div> </div>
</div> </div>
......
...@@ -113,7 +113,7 @@ export default { ...@@ -113,7 +113,7 @@ export default {
}; };
</script> </script>
<template> <template>
<div class="stage-panel-container"> <div class="stage-panel-container" data-testid="vsa-stage-table">
<div <div
v-if="isLoading" v-if="isLoading"
class="gl-display-flex gl-justify-content-center gl-align-items-center gl-w-full" class="gl-display-flex gl-justify-content-center gl-align-items-center gl-w-full"
......
...@@ -71,7 +71,7 @@ export const fetchStageData = ({ dispatch, getters }, stageId) => { ...@@ -71,7 +71,7 @@ export const fetchStageData = ({ dispatch, getters }, stageId) => {
groupId: currentGroupPath, groupId: currentGroupPath,
valueStreamId: currentValueStreamId, valueStreamId: currentValueStreamId,
stageId, stageId,
cycleAnalyticsRequestParams, params: cycleAnalyticsRequestParams,
}) })
.then(checkForDataError) .then(checkForDataError)
.then(({ data }) => dispatch('receiveStageDataSuccess', data)) .then(({ data }) => dispatch('receiveStageDataSuccess', data))
...@@ -114,7 +114,7 @@ export const fetchStageMedianValues = ({ dispatch, commit, getters }) => { ...@@ -114,7 +114,7 @@ export const fetchStageMedianValues = ({ dispatch, commit, getters }) => {
groupId: currentGroupPath, groupId: currentGroupPath,
valueStreamId: currentValueStreamId, valueStreamId: currentValueStreamId,
stageId, stageId,
cycleAnalyticsRequestParams, params: cycleAnalyticsRequestParams,
}), }),
), ),
) )
...@@ -193,7 +193,7 @@ export const fetchGroupStagesAndEvents = ({ dispatch, getters }) => { ...@@ -193,7 +193,7 @@ export const fetchGroupStagesAndEvents = ({ dispatch, getters }) => {
return Api.cycleAnalyticsGroupStagesAndEvents({ return Api.cycleAnalyticsGroupStagesAndEvents({
groupId, groupId,
valueStreamId, valueStreamId,
data: { params: {
start_date: created_after, start_date: created_after,
project_ids, project_ids,
}, },
......
...@@ -31,7 +31,7 @@ export const fetchDurationData = ({ dispatch, commit, rootGetters }) => { ...@@ -31,7 +31,7 @@ export const fetchDurationData = ({ dispatch, commit, rootGetters }) => {
groupId: currentGroupPath, groupId: currentGroupPath,
valueStreamId: currentValueStreamId, valueStreamId: currentValueStreamId,
stageId: slug, stageId: slug,
cycleAnalyticsRequestParams, params: cycleAnalyticsRequestParams,
}) })
.then(checkForDataError) .then(checkForDataError)
.then(({ data }) => ({ slug, selected: true, data })); .then(({ data }) => ({ slug, selected: true, data }));
......
...@@ -164,7 +164,7 @@ export default { ...@@ -164,7 +164,7 @@ export default {
.replace(':value_stream_id', valueStreamId) .replace(':value_stream_id', valueStreamId)
.replace(':stage_id', stageId); .replace(':stage_id', stageId);
return axios.get(url, { params: { ...params } }); return axios.get(url, { params });
}, },
cycleAnalyticsCreateStage({ groupId, valueStreamId, data }) { cycleAnalyticsCreateStage({ groupId, valueStreamId, data }) {
......
---
title: This fixes an issue where the request parameters would be missing on the Value
Stream Analytics page, so the charts would not reflect the filters applied.
merge_request: 42655
author:
type: fixed
...@@ -8,6 +8,8 @@ RSpec.describe 'Group value stream analytics filters and data', :js do ...@@ -8,6 +8,8 @@ RSpec.describe 'Group value stream analytics filters and data', :js do
let_it_be(:project) { create(:project, :repository, namespace: group, group: group, name: 'Cool fun project') } let_it_be(:project) { create(:project, :repository, namespace: group, group: group, name: 'Cool fun project') }
let_it_be(:sub_group) { create(:group, name: 'CA-sub-group', parent: group) } let_it_be(:sub_group) { create(:group, name: 'CA-sub-group', parent: group) }
let_it_be(:sub_group_project) { create(:project, :repository, namespace: group, group: sub_group, name: 'Cool sub group project') } let_it_be(:sub_group_project) { create(:project, :repository, namespace: group, group: sub_group, name: 'Cool sub group project') }
let_it_be(:group_label1) { create(:group_label, group: group) }
let_it_be(:group_label2) { create(:group_label, group: group) }
let(:milestone) { create(:milestone, project: project) } let(:milestone) { create(:milestone, project: project) }
let(:mr) { create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}") } let(:mr) { create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}") }
...@@ -287,6 +289,8 @@ RSpec.describe 'Group value stream analytics filters and data', :js do ...@@ -287,6 +289,8 @@ RSpec.describe 'Group value stream analytics filters and data', :js do
before do before do
create_cycle(user, project, issue, mr, milestone, pipeline) create_cycle(user, project, issue, mr, milestone, pipeline)
create(:labeled_issue, created_at: 5.days.ago, project: create(:project, group: group), labels: [group_label1])
create(:labeled_issue, created_at: 3.days.ago, project: create(:project, group: group), labels: [group_label2])
issue.metrics.update!(first_mentioned_in_commit_at: mr.created_at - 5.hours) issue.metrics.update!(first_mentioned_in_commit_at: mr.created_at - 5.hours)
mr.metrics.update!(first_deployed_to_production_at: mr.created_at + 2.hours, merged_at: mr.created_at + 1.hour) mr.metrics.update!(first_deployed_to_production_at: mr.created_at + 2.hours, merged_at: mr.created_at + 1.hour)
...@@ -297,54 +301,91 @@ RSpec.describe 'Group value stream analytics filters and data', :js do ...@@ -297,54 +301,91 @@ RSpec.describe 'Group value stream analytics filters and data', :js do
select_group select_group
end end
dummy_stages = [ stages_with_data = [
{ title: 'Issue', description: 'Time before an issue gets scheduled', events_count: 1, median: '5 days' }, { title: 'Issue', description: 'Time before an issue gets scheduled', events_count: 1, median: '5 days' },
{ title: 'Plan', description: 'Time before an issue starts implementation', events_count: 0, median: 'Not enough data' },
{ title: 'Code', description: 'Time until first merge request', events_count: 1, median: 'about 5 hours' }, { title: 'Code', description: 'Time until first merge request', events_count: 1, median: 'about 5 hours' },
{ title: 'Test', description: 'Total test time for all commits/merges', events_count: 0, median: 'Not enough data' },
{ title: 'Review', description: 'Time between merge request creation and merge/close', events_count: 1, median: 'about 1 hour' }, { title: 'Review', description: 'Time between merge request creation and merge/close', events_count: 1, median: 'about 1 hour' },
{ title: 'Staging', description: 'From merge request merge until deploy to production', events_count: 1, median: 'about 1 hour' } { title: 'Staging', description: 'From merge request merge until deploy to production', events_count: 1, median: 'about 1 hour' }
] ]
stages_without_data = [
{ title: 'Plan', description: 'Time before an issue starts implementation', events_count: 0, median: 'Not enough data' },
{ title: 'Test', description: 'Total test time for all commits/merges', events_count: 0, median: 'Not enough data' }
]
it 'each stage will have median values', :sidekiq_might_not_need_inline do it 'each stage will have median values', :sidekiq_might_not_need_inline do
stages = page.all('.stage-nav .stage-median').collect(&:text) stage_medians = page.all('.stage-nav .stage-median').collect(&:text)
stages.each_with_index do |median, index| expect(stage_medians).to eq(["5 days", "Not enough data", "about 5 hours", "Not enough data", "about 1 hour", "about 1 hour"])
expect(median).to eq(dummy_stages[index][:median])
end
end end
it 'each stage will display the events description when selected', :sidekiq_might_not_need_inline do it 'each stage will display the events description when selected', :sidekiq_might_not_need_inline do
dummy_stages.each do |stage| stages_without_data.each do |stage|
select_stage(stage[:title]) select_stage(stage[:title])
expect(page).not_to have_selector('.stage-events .events-description')
end
if stage[:events_count] == 0 stages_with_data.each do |stage|
expect(page).not_to have_selector('.stage-events .events-description') select_stage(stage[:title])
else expect(page.find('.stage-events .events-description').text).to have_text(_(stage[:description]))
expect(page.find('.stage-events .events-description').text).to have_text(_(stage[:description]))
end
end end
end end
it 'each stage with events will display the stage events list when selected', :sidekiq_might_not_need_inline do it 'each stage with events will display the stage events list when selected', :sidekiq_might_not_need_inline do
dummy_stages.each do |stage| stages_without_data.each do |stage|
select_stage(stage[:title]) select_stage(stage[:title])
expect(page).not_to have_selector('.stage-events .stage-event-item')
end
if stage[:events_count] == 0 stages_with_data.each do |stage|
expect(page).not_to have_selector('.stage-events .stage-event-item') select_stage(stage[:title])
else expect(page).to have_selector('.stage-events .stage-event-list')
expect(page).to have_selector('.stage-events .stage-event-list') expect(page.all('.stage-events .stage-event-item').length).to eq(stage[:events_count])
expect(page.all('.stage-events .stage-event-item').length).to eq(stage[:events_count])
end
end end
end end
it 'each stage will be selectable' do it 'each stage will be selectable' do
dummy_stages.each do |stage| [].concat(stages_without_data, stages_with_data).each do |stage|
select_stage(stage[:title]) select_stage(stage[:title])
expect(page.find('.stage-nav .active .stage-name').text).to eq(stage[:title]) expect(page.find('.stage-nav .active .stage-name').text).to eq(stage[:title])
end end
end end
it 'will have data available' do
expect(page.find('[data-testid="vsa-stage-table"]')).not_to have_text(_("We don't have enough data to show this stage."))
duration_chart_content = page.find('[data-testid="vsa-duration-chart"]')
expect(duration_chart_content).not_to have_text(_("There is no data available. Please change your selection."))
expect(duration_chart_content).to have_text(_('Total days to completion'))
tasks_by_type_chart_content = page.find('.js-tasks-by-type-chart')
expect(tasks_by_type_chart_content).not_to have_text(_("There is no data available. Please change your selection."))
end
context 'with filters applied' do
before do
visit "#{group_analytics_cycle_analytics_path(group)}?created_before=2019-12-31&created_after=2019-11-01"
wait_for_stages_to_load
end
it 'will filter the stage median values' do
stage_medians = page.all('.stage-nav .stage-median').collect(&:text)
expect(stage_medians).to eq([_("Not enough data")] * 6)
end
it 'will filter the data' do
expect(page.find('[data-testid="vsa-stage-table"]')).to have_text(_("We don't have enough data to show this stage."))
duration_chart_content = page.find('[data-testid="vsa-duration-chart"]')
expect(duration_chart_content).not_to have_text(_('Total days to completion'))
expect(duration_chart_content).to have_text(_("There is no data available. Please change your selection."))
tasks_by_type_chart_content = page.find('.js-tasks-by-type-chart')
expect(tasks_by_type_chart_content).to have_text(_("There is no data available. Please change your selection."))
end
end
end end
end end
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DurationChart renders the duration chart 1`] = ` exports[`DurationChart renders the duration chart 1`] = `
"<div class=\\"gl-display-flex gl-flex-direction-column\\"> "<div data-testid=\\"vsa-duration-chart\\" class=\\"gl-display-flex gl-flex-direction-column\\">
<h4 class=\\"gl-mt-0\\">Days to completion</h4> <h4 class=\\"gl-mt-0\\">Days to completion</h4>
<stagedropdownfilter-stub stages=\\"[object Object],[object Object],[object Object]\\" label=\\"stage dropdown\\" class=\\"gl-ml-auto\\"></stagedropdownfilter-stub> <stagedropdownfilter-stub stages=\\"[object Object],[object Object],[object Object]\\" label=\\"stage dropdown\\" class=\\"gl-ml-auto\\"></stagedropdownfilter-stub>
<scatterplot-stub xaxistitle=\\"Date\\" yaxistitle=\\"Total days to completion\\" scatterdata=\\"2019-01-01,29,2019-01-01,2019-01-02,100,2019-01-02\\" medianlinedata=\\"\\" tooltipdateformat=\\"mmm d, yyyy\\"></scatterplot-stub> <scatterplot-stub xaxistitle=\\"Date\\" yaxistitle=\\"Total days to completion\\" scatterdata=\\"2019-01-01,29,2019-01-01,2019-01-02,100,2019-01-02\\" medianlinedata=\\"\\" tooltipdateformat=\\"mmm d, yyyy\\"></scatterplot-stub>
......
...@@ -59,7 +59,7 @@ function createComponent({ ...@@ -59,7 +59,7 @@ function createComponent({
describe('DurationChart', () => { describe('DurationChart', () => {
let wrapper; let wrapper;
const findNoDataContainer = _wrapper => _wrapper.find({ ref: 'duration-chart-no-data' }); const findContainer = _wrapper => _wrapper.find('[data-testid="vsa-duration-chart"]');
const findScatterPlot = _wrapper => _wrapper.find(Scatterplot); const findScatterPlot = _wrapper => _wrapper.find(Scatterplot);
const findStageDropdown = _wrapper => _wrapper.find(StageDropdownFilter); const findStageDropdown = _wrapper => _wrapper.find(StageDropdownFilter);
const findLoader = _wrapper => _wrapper.find(ChartSkeletonLoader); const findLoader = _wrapper => _wrapper.find(ChartSkeletonLoader);
...@@ -133,7 +133,7 @@ describe('DurationChart', () => { ...@@ -133,7 +133,7 @@ describe('DurationChart', () => {
}); });
it('renders the no data available message', () => { it('renders the no data available message', () => {
expect(findNoDataContainer(wrapper).text()).toEqual( expect(findContainer(wrapper).text()).toContain(
'There is no data available. Please change your selection.', 'There is no data available. Please change your selection.',
); );
}); });
......
...@@ -26822,6 +26822,9 @@ msgstr "" ...@@ -26822,6 +26822,9 @@ msgstr ""
msgid "Total cores (CPUs)" msgid "Total cores (CPUs)"
msgstr "" msgstr ""
msgid "Total days to completion"
msgstr ""
msgid "Total issues" msgid "Total issues"
msgstr "" msgstr ""
......
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