Commit d956a648 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Update multiple value stream specs

Updates tests to include states when the
feature flag is on and also off.

Adds additional blocks with / without an existing
value stream when the feature flag is on.

Fix cycle_analytics charts specs

Update VSA chart specs to include blocks
for the aggregation feature flag.

Fix error message for invalid date ranges

Fix flash of loading state

Fix empty state selector

Fixes the empty state selector in the charts
filters and multiple value stream specs
parent d6c03eb1
This diff is collapsed.
...@@ -79,7 +79,7 @@ export default { ...@@ -79,7 +79,7 @@ export default {
'hasValueStreams', 'hasValueStreams',
]), ]),
shouldRenderEmptyState() { shouldRenderEmptyState() {
return !this.isLoadingValueStreams && !this.hasValueStreams; return this.isLoadingValueStreams || !this.hasValueStreams;
}, },
shouldDisplayFilters() { shouldDisplayFilters() {
return !this.errorCode && !this.hasNoAccessError; return !this.errorCode && !this.hasNoAccessError;
...@@ -203,7 +203,9 @@ export default { ...@@ -203,7 +203,9 @@ export default {
<div> <div>
<value-stream-empty-state <value-stream-empty-state
v-if="shouldRenderEmptyState" v-if="shouldRenderEmptyState"
:is-loading="isLoadingValueStreams"
:empty-state-svg-path="emptyStateSvgPath" :empty-state-svg-path="emptyStateSvgPath"
:has-date-range-error="!hasDateRangeSet"
/> />
<div v-else class="gl-max-w-full"> <div v-else class="gl-max-w-full">
<div <div
......
...@@ -76,6 +76,7 @@ export default { ...@@ -76,6 +76,7 @@ export default {
:svg-path="emptyStateSvgPath" :svg-path="emptyStateSvgPath"
:title="title" :title="title"
:description="description" :description="description"
data-testid="vsa-empty-state"
> >
<template v-if="!hasDateRangeError" #actions> <template v-if="!hasDateRangeError" #actions>
<gl-button <gl-button
......
...@@ -12,6 +12,8 @@ RSpec.describe 'Value stream analytics charts', :js do ...@@ -12,6 +12,8 @@ RSpec.describe 'Value stream analytics charts', :js do
let_it_be(:group_label2) { create(:group_label, group: group) } let_it_be(:group_label2) { create(:group_label, group: group) }
let_it_be(:label) { create(:group_label, group: group2) } let_it_be(:label) { create(:group_label, group: group2) }
empty_state_selector = '[data-testid="vsa-empty-state"]'
3.times do |i| 3.times do |i|
let_it_be("issue_#{i}".to_sym) { create(:issue, title: "New Issue #{i}", project: project, created_at: 2.days.ago) } let_it_be("issue_#{i}".to_sym) { create(:issue, title: "New Issue #{i}", project: project, created_at: 2.days.ago) }
end end
...@@ -32,15 +34,14 @@ RSpec.describe 'Value stream analytics charts', :js do ...@@ -32,15 +34,14 @@ RSpec.describe 'Value stream analytics charts', :js do
sign_in(user) sign_in(user)
end end
context 'Duration chart' do shared_examples 'has the empty state' do
let(:custom_value_stream_name) { "New created value stream" } it 'renders the empty state' do
expect(page).to have_selector(empty_state_selector)
before do expect(page).to have_text(s_('CycleAnalytics|Custom value streams to measure your DevSecOps lifecycle'))
select_group(group)
create_custom_value_stream(custom_value_stream_name)
end end
end
shared_examples 'has the duration chart' do
it 'displays data for all stages on the overview' do it 'displays data for all stages on the overview' do
page.within('[data-testid="vsa-path-navigation"]') do page.within('[data-testid="vsa-path-navigation"]') do
click_button "Overview" click_button "Overview"
...@@ -58,72 +59,132 @@ RSpec.describe 'Value stream analytics charts', :js do ...@@ -58,72 +59,132 @@ RSpec.describe 'Value stream analytics charts', :js do
end end
end end
describe 'Tasks by type chart', :js do shared_examples 'has the tasks by type chart' do
filters_selector = '.js-tasks-by-type-chart-filters' context 'with data available' do
filters_selector = '.js-tasks-by-type-chart-filters'
before do before do
stub_licensed_features(cycle_analytics_for_groups: true, type_of_work_analytics: true) mr_issue = create(:labeled_issue, created_at: 5.days.ago, project: create(:project, group: group), labels: [group_label2])
create(:merge_request, iid: mr_issue.id, created_at: 3.days.ago, source_project: project, labels: [group_label1, group_label2])
project.add_maintainer(user) 3.times do |i|
create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label1])
create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label2])
end
sign_in(user) select_group(group)
end end
context 'enabled' do it 'displays the chart' do
context 'with data available' do expect(page).to have_text(s_('CycleAnalytics|Type of work'))
before do
mr_issue = create(:labeled_issue, created_at: 5.days.ago, project: create(:project, group: group), labels: [group_label2])
create(:merge_request, iid: mr_issue.id, created_at: 3.days.ago, source_project: project, labels: [group_label1, group_label2])
3.times do |i| expect(page).to have_text(s_('CycleAnalytics|Tasks by type'))
create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label1]) end
create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label2])
end
select_group(group) it 'has 2 labels selected' do
end expect(page).to have_text('Showing Issues and 2 labels')
end
it 'displays the chart' do it 'has chart filters' do
expect(page).to have_text(s_('CycleAnalytics|Type of work')) expect(page).to have_css(filters_selector)
end
expect(page).to have_text(s_('CycleAnalytics|Tasks by type')) it 'can update the filters' do
page.within filters_selector do
find('.dropdown-toggle').click
first_selected_label = all('[data-testid="type-of-work-filters-label"] .dropdown-item.active').first
first_selected_label.click
end end
it 'has 2 labels selected' do expect(page).to have_text('Showing Issues and 1 label')
expect(page).to have_text('Showing Issues and 2 labels')
end
it 'has chart filters' do page.within filters_selector do
expect(page).to have_css(filters_selector) find('.dropdown-toggle').click
find('[data-testid="type-of-work-filters-subject"] label', text: 'Merge Requests').click
end end
it 'can update the filters' do expect(page).to have_text('Showing Merge Requests and 1 label')
page.within filters_selector do end
find('.dropdown-toggle').click end
first_selected_label = all('[data-testid="type-of-work-filters-label"] .dropdown-item.active').first
first_selected_label.click context 'no data available' do
end before do
select_group(group)
end
expect(page).to have_text('Showing Issues and 1 label') it 'shows the no data available message' do
expect(page).to have_text(s_('CycleAnalytics|Type of work'))
page.within filters_selector do expect(page).to have_text(_('There is no data available. Please change your selection.'))
find('.dropdown-toggle').click end
find('[data-testid="type-of-work-filters-subject"] label', text: 'Merge Requests').click end
end end
expect(page).to have_text('Showing Merge Requests and 1 label') context 'Duration chart' do
context 'use_vsa_aggregated_tables feature flag off' do
before do
stub_feature_flags(use_vsa_aggregated_tables: false)
select_group(group)
end
it_behaves_like 'has the duration chart'
end
context 'use_vsa_aggregated_tables feature flag on' do
context 'with no value streams' do
before do
select_group(group, empty_state_selector)
end end
it_behaves_like 'has the empty state'
end end
context 'no data available' do context 'with a value stream' do
before do before do
create(:cycle_analytics_group_value_stream, group: group, name: 'First value stream')
select_group(group) select_group(group)
end end
it 'shows the no data available message' do it_behaves_like 'has the duration chart'
expect(page).to have_text(s_('CycleAnalytics|Type of work')) end
end
end
describe 'Tasks by type chart', :js do
before do
stub_licensed_features(cycle_analytics_for_groups: true, type_of_work_analytics: true)
project.add_maintainer(user)
sign_in(user)
end
context 'type_of_work_analytics enabled' do
context 'use_vsa_aggregated_tables feature flag off' do
before do
stub_feature_flags(use_vsa_aggregated_tables: false)
end
it_behaves_like 'has the tasks by type chart'
end
context 'use_vsa_aggregated_tables feature flag on' do
context 'with no value streams' do
before do
select_group(group, empty_state_selector)
end
it_behaves_like 'has the empty state'
end
context 'with a value stream' do
before do
create(:cycle_analytics_group_value_stream, group: group, name: 'First value stream')
end
expect(page).to have_text(_('There is no data available. Please change your selection.')) it_behaves_like 'has the tasks by type chart'
end end
end end
end end
......
...@@ -18,14 +18,13 @@ RSpec.describe 'Multiple value streams', :js do ...@@ -18,14 +18,13 @@ RSpec.describe 'Multiple value streams', :js do
let(:extended_form_fields_selector) { '[data-testid="extended-form-fields"]' } let(:extended_form_fields_selector) { '[data-testid="extended-form-fields"]' }
let(:preset_selector) { '[data-testid="vsa-preset-selector"]' } let(:preset_selector) { '[data-testid="vsa-preset-selector"]' }
let!(:default_value_stream) { create(:cycle_analytics_group_value_stream, group: group, name: 'default') } let(:empty_state_selector) { '[data-testid="vsa-empty-state"]' }
3.times do |i| 3.times do |i|
let_it_be("issue_#{i}".to_sym) { create(:issue, title: "New Issue #{i}", project: project, created_at: 2.days.ago) } let_it_be("issue_#{i}".to_sym) { create(:issue, title: "New Issue #{i}", project: project, created_at: 2.days.ago) }
end end
before do before do
stub_feature_flags(use_vsa_aggregated_tables: false)
stub_licensed_features(cycle_analytics_for_groups: true, type_of_work_analytics: true) stub_licensed_features(cycle_analytics_for_groups: true, type_of_work_analytics: true)
sign_in(user) sign_in(user)
...@@ -199,7 +198,7 @@ RSpec.describe 'Multiple value streams', :js do ...@@ -199,7 +198,7 @@ RSpec.describe 'Multiple value streams', :js do
end end
end end
describe 'With a group' do shared_examples 'create group value streams' do
name = 'group value stream' name = 'group value stream'
before do before do
...@@ -211,7 +210,7 @@ RSpec.describe 'Multiple value streams', :js do ...@@ -211,7 +210,7 @@ RSpec.describe 'Multiple value streams', :js do
it_behaves_like 'delete a value stream', name it_behaves_like 'delete a value stream', name
end end
describe 'With a sub group' do shared_examples 'create sub group value streams' do
name = 'sub group value stream' name = 'sub group value stream'
before do before do
...@@ -222,4 +221,42 @@ RSpec.describe 'Multiple value streams', :js do ...@@ -222,4 +221,42 @@ RSpec.describe 'Multiple value streams', :js do
it_behaves_like 'update a value stream', name it_behaves_like 'update a value stream', name
it_behaves_like 'delete a value stream', name it_behaves_like 'delete a value stream', name
end end
context 'use_vsa_aggregated_tables feature flag off' do
before do
stub_feature_flags(use_vsa_aggregated_tables: false)
end
it_behaves_like 'create group value streams'
it_behaves_like 'create sub group value streams'
end
context 'use_vsa_aggregated_tables feature flag on' do
context 'without a value stream' do
before do
select_group(group, empty_state_selector)
end
it 'renders the empty state' do
expect(page).to have_text(s_('CycleAnalytics|Custom value streams to measure your DevSecOps lifecycle'))
end
it 'can navigate to the create value stream form' do
page.find('[data-testid="create-value-stream-button"]').click
expect(page).to have_selector('[data-testid="value-stream-form-modal"]')
end
end
context 'with a value stream' do
before do
# ensure we have a value stream already available
create(:cycle_analytics_group_value_stream, group: group, name: 'default')
create(:cycle_analytics_group_value_stream, group: sub_group, name: 'default')
end
it_behaves_like 'create group value streams'
it_behaves_like 'create sub group value streams'
end
end
end end
...@@ -9,6 +9,7 @@ import DurationChart from 'ee/analytics/cycle_analytics/components/duration_char ...@@ -9,6 +9,7 @@ import DurationChart from 'ee/analytics/cycle_analytics/components/duration_char
import TypeOfWorkCharts from 'ee/analytics/cycle_analytics/components/type_of_work_charts.vue'; import TypeOfWorkCharts from 'ee/analytics/cycle_analytics/components/type_of_work_charts.vue';
import ValueStreamSelect from 'ee/analytics/cycle_analytics/components/value_stream_select.vue'; import ValueStreamSelect from 'ee/analytics/cycle_analytics/components/value_stream_select.vue';
import ValueStreamAggregationStatus from 'ee/analytics/cycle_analytics/components/value_stream_aggregation_status.vue'; import ValueStreamAggregationStatus from 'ee/analytics/cycle_analytics/components/value_stream_aggregation_status.vue';
import ValueStreamEmptyState from 'ee/analytics/cycle_analytics/components/value_stream_empty_state.vue';
import createStore from 'ee/analytics/cycle_analytics/store'; import createStore from 'ee/analytics/cycle_analytics/store';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { import {
...@@ -195,11 +196,12 @@ describe('EE Value Stream Analytics component', () => { ...@@ -195,11 +196,12 @@ describe('EE Value Stream Analytics component', () => {
expect(wrapper.findComponent(ValueStreamSelect).exists()).toBe(flag); expect(wrapper.findComponent(ValueStreamSelect).exists()).toBe(flag);
}; };
describe('without a group', () => { describe('with no value streams', () => {
beforeEach(async () => { beforeEach(async () => {
const { group, ...stateWithoutGroup } = initialCycleAnalyticsState;
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
wrapper = await createComponent({ initialState: stateWithoutGroup }); wrapper = await createComponent({
initialState: { ...initialCycleAnalyticsState, valueStreams: [] },
});
}); });
afterEach(() => { afterEach(() => {
...@@ -209,10 +211,10 @@ describe('EE Value Stream Analytics component', () => { ...@@ -209,10 +211,10 @@ describe('EE Value Stream Analytics component', () => {
}); });
it('displays an empty state', () => { it('displays an empty state', () => {
const emptyState = wrapper.findComponent(GlEmptyState); const emptyState = wrapper.findComponent(ValueStreamEmptyState);
expect(emptyState.exists()).toBe(true); expect(emptyState.exists()).toBe(true);
expect(emptyState.props('svgPath')).toBe(emptyStateSvgPath); expect(emptyState.props('emptyStateSvgPath')).toBe(emptyStateSvgPath);
}); });
it('does not display the metrics cards', () => { it('does not display the metrics cards', () => {
......
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