Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
857d228b
Commit
857d228b
authored
Jul 05, 2021
by
Ezekiel Kigbo
Committed by
Nicolò Maria Mezzopera
Jul 05, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moves the VSA filters into a reusable component
parent
2cfa4d93
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
313 additions
and
173 deletions
+313
-173
ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
...javascripts/analytics/cycle_analytics/components/base.vue
+22
-51
ee/app/assets/javascripts/analytics/cycle_analytics/components/value_stream_filters.vue
...ytics/cycle_analytics/components/value_stream_filters.vue
+94
-0
ee/app/assets/javascripts/analytics/cycle_analytics/store/actions.js
...ts/javascripts/analytics/cycle_analytics/store/actions.js
+2
-2
ee/app/assets/javascripts/analytics/cycle_analytics/store/getters.js
...ts/javascripts/analytics/cycle_analytics/store/getters.js
+4
-4
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/duration_chart/getters.js
...s/cycle_analytics/store/modules/duration_chart/getters.js
+6
-2
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/type_of_work/getters.js
...ics/cycle_analytics/store/modules/type_of_work/getters.js
+11
-6
ee/app/assets/javascripts/analytics/cycle_analytics/store/mutations.js
.../javascripts/analytics/cycle_analytics/store/mutations.js
+7
-7
ee/app/assets/javascripts/analytics/cycle_analytics/store/state.js
...sets/javascripts/analytics/cycle_analytics/store/state.js
+2
-2
ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js
...rontend/analytics/cycle_analytics/components/base_spec.js
+12
-53
ee/spec/frontend/analytics/cycle_analytics/components/value_stream_filters_spec.js
...s/cycle_analytics/components/value_stream_filters_spec.js
+91
-0
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
+3
-3
ee/spec/frontend/analytics/cycle_analytics/store/actions_spec.js
.../frontend/analytics/cycle_analytics/store/actions_spec.js
+8
-8
ee/spec/frontend/analytics/cycle_analytics/store/getters_spec.js
.../frontend/analytics/cycle_analytics/store/getters_spec.js
+4
-4
ee/spec/frontend/analytics/cycle_analytics/store/modules/duration_chart/actions_spec.js
...le_analytics/store/modules/duration_chart/actions_spec.js
+4
-4
ee/spec/frontend/analytics/cycle_analytics/store/modules/duration_chart/getters_spec.js
...le_analytics/store/modules/duration_chart/getters_spec.js
+4
-4
ee/spec/frontend/analytics/cycle_analytics/store/modules/type_of_work/actions_spec.js
...ycle_analytics/store/modules/type_of_work/actions_spec.js
+8
-2
ee/spec/frontend/analytics/cycle_analytics/store/modules/type_of_work/getters_spec.js
...ycle_analytics/store/modules/type_of_work/getters_spec.js
+3
-3
ee/spec/frontend/analytics/cycle_analytics/store/mutations_spec.js
...rontend/analytics/cycle_analytics/store/mutations_spec.js
+5
-5
ee/spec/frontend/analytics/cycle_analytics/utils_spec.js
ee/spec/frontend/analytics/cycle_analytics/utils_spec.js
+23
-13
No files found.
ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
View file @
857d228b
...
...
@@ -4,29 +4,23 @@ import { mapActions, mapState, mapGetters } from 'vuex';
import
PathNavigation
from
'
~/cycle_analytics/components/path_navigation.vue
'
;
import
{
OVERVIEW_STAGE_ID
}
from
'
~/cycle_analytics/constants
'
;
import
UrlSync
from
'
~/vue_shared/components/url_sync.vue
'
;
import
DateRange
from
'
../../shared/components/daterange.vue
'
;
import
ProjectsDropdownFilter
from
'
../../shared/components/projects_dropdown_filter.vue
'
;
import
{
DATE_RANGE_LIMIT
}
from
'
../../shared/constants
'
;
import
{
toYmd
}
from
'
../../shared/utils
'
;
import
{
PROJECTS_PER_PAGE
}
from
'
../constants
'
;
import
DurationChart
from
'
./duration_chart.vue
'
;
import
FilterBar
from
'
./filter_bar.vue
'
;
import
Metrics
from
'
./metrics.vue
'
;
import
StageTable
from
'
./stage_table.vue
'
;
import
TypeOfWorkCharts
from
'
./type_of_work_charts.vue
'
;
import
ValueStreamFilters
from
'
./value_stream_filters.vue
'
;
import
ValueStreamSelect
from
'
./value_stream_select.vue
'
;
export
default
{
name
:
'
CycleAnalytics
'
,
components
:
{
DateRange
,
DurationChart
,
GlEmptyState
,
ProjectsDropdownFilter
,
TypeOfWorkCharts
,
StageTable
,
PathNavigation
,
FilterBar
,
ValueStreamFilters
,
ValueStreamSelect
,
UrlSync
,
Metrics
,
...
...
@@ -56,8 +50,8 @@ export default {
'
stages
'
,
'
selectedStageEvents
'
,
'
errorCode
'
,
'
startDate
'
,
'
endDat
e
'
,
'
createdAfter
'
,
'
createdBefor
e
'
,
'
isLoadingValueStreams
'
,
'
selectedStageError
'
,
'
selectedValueStream
'
,
...
...
@@ -90,7 +84,7 @@ export default {
return
Boolean
(
!
this
.
shouldRenderEmptyState
&&
!
this
.
isLoadingValueStreams
);
},
hasDateRangeSet
()
{
return
this
.
startDate
&&
this
.
endDat
e
;
return
this
.
createdAfter
&&
this
.
createdBefor
e
;
},
query
()
{
const
selectedProjectIds
=
this
.
selectedProjectIds
?.
length
?
this
.
selectedProjectIds
:
null
;
...
...
@@ -109,8 +103,8 @@ export default {
return
{
value_stream_id
:
this
.
selectedValueStream
?.
id
||
null
,
project_ids
:
selectedProjectIds
,
created_after
:
toYmd
(
this
.
startDate
),
created_before
:
toYmd
(
this
.
endDat
e
),
created_after
:
toYmd
(
this
.
createdAfter
),
created_before
:
toYmd
(
this
.
createdBefor
e
),
stage_id
:
(
!
this
.
isOverviewStageSelected
&&
this
.
selectedStage
?.
id
)
||
null
,
// the `overview` stage is always the default, so dont persist the id if its selected
...
paginationUrlParams
,
};
...
...
@@ -118,12 +112,6 @@ export default {
stageCount
()
{
return
this
.
activeStages
.
length
;
},
projectsQueryParams
()
{
return
{
first
:
PROJECTS_PER_PAGE
,
includeSubgroups
:
true
,
};
},
},
methods
:
{
...
mapActions
([
...
...
@@ -147,12 +135,16 @@ export default {
this
.
updateStageTablePagination
({
...
this
.
pagination
,
page
:
1
});
}
},
onSetDateRange
({
startDate
,
endDate
})
{
this
.
setDateRange
({
createdAfter
:
new
Date
(
startDate
),
createdBefore
:
new
Date
(
endDate
),
});
},
onHandleUpdatePagination
(
data
)
{
this
.
updateStageTablePagination
(
data
);
},
},
multiProjectSelect
:
true
,
maxDateRange
:
DATE_RANGE_LIMIT
,
};
</
script
>
<
template
>
...
...
@@ -183,36 +175,15 @@ export default {
:selected-stage=
"selectedStage"
@
selected=
"onStageSelect"
/>
<div
class=
"gl-mt-3 gl-py-2 gl-px-3 bg-gray-light border-top border-bottom"
>
<filter-bar
v-if=
"shouldDisplayFilters"
class=
"js-filter-bar filtered-search-box gl-display-flex gl-mb-2 gl-mr-3 gl-border-none"
:group-path=
"currentGroupPath"
/>
<div
v-if=
"shouldDisplayFilters"
class=
"gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-justify-content-space-between"
>
<projects-dropdown-filter
:key=
"currentGroup.id"
class=
"js-projects-dropdown-filter project-select gl-mb-2 gl-lg-mb-0"
:group-id=
"currentGroup.id"
:group-namespace=
"currentGroupPath"
:query-params=
"projectsQueryParams"
:multi-select=
"$options.multiProjectSelect"
:default-projects=
"selectedProjects"
@
selected=
"onProjectsSelect"
/>
<date-range
:start-date=
"startDate"
:end-date=
"endDate"
:max-date-range=
"$options.maxDateRange"
:include-selected-date=
"true"
class=
"js-daterange-picker"
@
change=
"setDateRange"
/>
</div>
</div>
<value-stream-filters
:group-id=
"currentGroup.id"
:group-path=
"currentGroupPath"
:selected-projects=
"selectedProjects"
:start-date=
"createdAfter"
:end-date=
"createdBefore"
@
selectProject=
"onProjectsSelect"
@
setDateRange=
"onSetDateRange"
/>
</div>
<div
v-if=
"!shouldRenderEmptyState"
class=
"cycle-analytics gl-mt-2"
>
<gl-empty-state
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/components/value_stream_filters.vue
0 → 100644
View file @
857d228b
<
script
>
import
DateRange
from
'
../../shared/components/daterange.vue
'
;
import
ProjectsDropdownFilter
from
'
../../shared/components/projects_dropdown_filter.vue
'
;
import
{
DATE_RANGE_LIMIT
}
from
'
../../shared/constants
'
;
import
{
PROJECTS_PER_PAGE
}
from
'
../constants
'
;
import
FilterBar
from
'
./filter_bar.vue
'
;
export
default
{
name
:
'
ValueStreamFilters
'
,
components
:
{
DateRange
,
ProjectsDropdownFilter
,
FilterBar
,
},
props
:
{
selectedProjects
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
hasProjectFilter
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
hasDateRangeFilter
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
groupId
:
{
type
:
Number
,
required
:
true
,
},
groupPath
:
{
type
:
String
,
required
:
true
,
},
startDate
:
{
type
:
Date
,
required
:
false
,
default
:
null
,
},
endDate
:
{
type
:
Date
,
required
:
false
,
default
:
null
,
},
},
computed
:
{
projectsQueryParams
()
{
return
{
first
:
PROJECTS_PER_PAGE
,
includeSubgroups
:
true
,
};
},
},
multiProjectSelect
:
true
,
maxDateRange
:
DATE_RANGE_LIMIT
,
};
</
script
>
<
template
>
<div
class=
"gl-mt-3 gl-py-2 gl-px-3 bg-gray-light border-top border-bottom"
>
<filter-bar
class=
"js-filter-bar filtered-search-box gl-display-flex gl-mb-2 gl-mr-3 gl-border-none"
:group-path=
"groupPath"
/>
<div
v-if=
"hasDateRangeFilter || hasProjectFilter"
class=
"gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-justify-content-space-between"
>
<projects-dropdown-filter
v-if=
"hasProjectFilter"
:key=
"groupId"
class=
"js-projects-dropdown-filter project-select gl-mb-2 gl-lg-mb-0"
:group-id=
"groupId"
:group-namespace=
"groupPath"
:query-params=
"projectsQueryParams"
:multi-select=
"$options.multiProjectSelect"
:default-projects=
"selectedProjects"
@
selected=
"$emit('selectProject', $event)"
/>
<date-range
v-if=
"hasDateRangeFilter"
:start-date=
"startDate"
:end-date=
"endDate"
:max-date-range=
"$options.maxDateRange"
:include-selected-date=
"true"
class=
"js-daterange-picker"
@
change=
"$emit('setDateRange', $event)"
/>
</div>
</div>
</
template
>
ee/app/assets/javascripts/analytics/cycle_analytics/store/actions.js
View file @
857d228b
...
...
@@ -34,9 +34,9 @@ export const setSelectedStage = ({ commit }, stage) => commit(types.SET_SELECTED
export
const
setDateRange
=
(
{
commit
,
dispatch
,
getters
:
{
isOverviewStageSelected
},
state
:
{
selectedStage
}
},
{
startDate
,
endDat
e
},
{
createdAfter
,
createdBefor
e
},
)
=>
{
commit
(
types
.
SET_DATE_RANGE
,
{
startDate
,
endDate
});
commit
(
types
.
SET_DATE_RANGE
,
{
createdBefore
,
createdAfter
});
if
(
selectedStage
&&
!
isOverviewStageSelected
)
dispatch
(
'
fetchStageData
'
,
selectedStage
.
id
);
return
dispatch
(
'
fetchCycleAnalyticsData
'
);
};
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/getters.js
View file @
857d228b
...
...
@@ -21,8 +21,8 @@ export const selectedProjectIds = ({ selectedProjects }) =>
export
const
cycleAnalyticsRequestParams
=
(
state
,
getters
)
=>
{
const
{
startDate
=
null
,
endDat
e
=
null
,
createdAfter
=
null
,
createdBefor
e
=
null
,
filters
:
{
authors
:
{
selected
:
selectedAuthor
},
milestones
:
{
selected
:
selectedMilestone
},
...
...
@@ -40,8 +40,8 @@ export const cycleAnalyticsRequestParams = (state, getters) => {
return
{
project_ids
:
getters
.
selectedProjectIds
,
created_after
:
startDate
?
dateFormat
(
startDate
,
dateFormats
.
isoDate
)
:
null
,
created_before
:
endDate
?
dateFormat
(
endDat
e
,
dateFormats
.
isoDate
)
:
null
,
created_after
:
createdAfter
?
dateFormat
(
createdAfter
,
dateFormats
.
isoDate
)
:
null
,
created_before
:
createdBefore
?
dateFormat
(
createdBefor
e
,
dateFormats
.
isoDate
)
:
null
,
...
filterBarQuery
,
};
};
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/duration_chart/getters.js
View file @
857d228b
import
{
getDurationChartData
}
from
'
../../../utils
'
;
export
const
durationChartPlottableData
=
(
state
,
_
,
rootState
)
=>
{
const
{
startDate
,
endDat
e
}
=
rootState
;
const
{
createdAfter
,
createdBefor
e
}
=
rootState
;
const
{
durationData
}
=
state
;
const
selectedStagesDurationData
=
durationData
.
filter
((
stage
)
=>
stage
.
selected
);
const
plottableData
=
getDurationChartData
(
selectedStagesDurationData
,
startDate
,
endDate
);
const
plottableData
=
getDurationChartData
(
selectedStagesDurationData
,
createdAfter
,
createdBefore
,
);
return
plottableData
.
length
?
plottableData
:
[];
};
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/type_of_work/getters.js
View file @
857d228b
...
...
@@ -2,24 +2,29 @@ import { getTasksByTypeData } from '../../../utils';
export
const
selectedTasksByTypeFilters
=
(
state
=
{},
_
,
rootState
=
{})
=>
{
const
{
selectedLabelIds
=
[],
subject
}
=
state
;
const
{
currentGroup
,
selectedProjectIds
=
[],
startDate
=
null
,
endDate
=
null
}
=
rootState
;
const
{
currentGroup
,
selectedProjectIds
=
[],
createdAfter
=
null
,
createdBefore
=
null
,
}
=
rootState
;
return
{
currentGroup
,
selectedProjectIds
,
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
selectedLabelIds
,
subject
,
};
};
export
const
tasksByTypeChartData
=
({
data
=
[]
}
=
{},
_
,
rootState
=
{})
=>
{
const
{
startDate
=
null
,
endDat
e
=
null
}
=
rootState
;
const
{
createdAfter
=
null
,
createdBefor
e
=
null
}
=
rootState
;
return
data
.
length
?
getTasksByTypeData
({
data
,
startDate
,
endDate
,
startDate
:
createdAfter
,
endDate
:
createdBefore
,
})
:
{
groupBy
:
[],
data
:
[]
};
};
ee/app/assets/javascripts/analytics/cycle_analytics/store/mutations.js
View file @
857d228b
...
...
@@ -14,9 +14,9 @@ export default {
[
types
.
SET_SELECTED_STAGE
](
state
,
rawData
)
{
state
.
selectedStage
=
convertObjectPropsToCamelCase
(
rawData
);
},
[
types
.
SET_DATE_RANGE
](
state
,
{
startDate
,
endDate
})
{
state
.
startDate
=
startDat
e
;
state
.
endDate
=
endDate
;
[
types
.
SET_DATE_RANGE
](
state
,
{
createdBefore
,
createdAfter
})
{
state
.
createdBefore
=
createdBefor
e
;
state
.
createdAfter
=
createdAfter
;
},
[
types
.
SET_STAGE_EVENTS
](
state
,
data
=
[])
{
state
.
formEvents
=
data
.
map
((
ev
)
=>
convertObjectPropsToCamelCase
(
ev
,
{
deep
:
true
}));
...
...
@@ -88,8 +88,8 @@ export default {
state
,
{
group
=
null
,
createdAfter
:
startDate
=
null
,
createdBefore
:
endDate
=
null
,
createdAfter
=
null
,
createdBefore
=
null
,
selectedProjects
=
[],
selectedValueStream
=
{},
defaultStageConfig
=
[],
...
...
@@ -100,8 +100,8 @@ export default {
state
.
currentGroup
=
group
;
state
.
selectedProjects
=
selectedProjects
;
state
.
selectedValueStream
=
selectedValueStream
;
state
.
startDate
=
startDat
e
;
state
.
endDate
=
endDate
;
state
.
createdBefore
=
createdBefor
e
;
state
.
createdAfter
=
createdAfter
;
state
.
defaultStageConfig
=
defaultStageConfig
;
Vue
.
set
(
state
,
'
pagination
'
,
{
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/state.js
View file @
857d228b
...
...
@@ -4,8 +4,8 @@ export default () => ({
featureFlags
:
{},
defaultStageConfig
:
[],
startDate
:
null
,
endDat
e
:
null
,
createdAfter
:
null
,
createdBefor
e
:
null
,
isLoading
:
false
,
isLoadingStage
:
false
,
...
...
ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js
View file @
857d228b
...
...
@@ -5,14 +5,12 @@ import MockAdapter from 'axios-mock-adapter';
import
Vuex
from
'
vuex
'
;
import
Component
from
'
ee/analytics/cycle_analytics/components/base.vue
'
;
import
DurationChart
from
'
ee/analytics/cycle_analytics/components/duration_chart.vue
'
;
import
FilterBar
from
'
ee/analytics/cycle_analytics/components/filter_bar.vue
'
;
import
Metrics
from
'
ee/analytics/cycle_analytics/components/metrics.vue
'
;
import
StageTable
from
'
ee/analytics/cycle_analytics/components/stage_table.vue
'
;
import
TypeOfWorkCharts
from
'
ee/analytics/cycle_analytics/components/type_of_work_charts.vue
'
;
import
ValueStreamFilters
from
'
ee/analytics/cycle_analytics/components/value_stream_filters.vue
'
;
import
ValueStreamSelect
from
'
ee/analytics/cycle_analytics/components/value_stream_select.vue
'
;
import
createStore
from
'
ee/analytics/cycle_analytics/store
'
;
import
Daterange
from
'
ee/analytics/shared/components/daterange.vue
'
;
import
ProjectsDropdownFilter
from
'
ee/analytics/shared/components/projects_dropdown_filter.vue
'
;
import
{
toYmd
}
from
'
ee/analytics/shared/utils
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
PathNavigation
from
'
~/cycle_analytics/components/path_navigation.vue
'
;
...
...
@@ -55,8 +53,8 @@ const [selectedValueStream] = mockData.valueStreams;
const
initialCycleAnalyticsState
=
{
selectedValueStream
,
createdAfter
:
mockData
.
startDate
,
createdBefore
:
mockData
.
endDat
e
,
createdAfter
:
mockData
.
createdAfter
,
createdBefore
:
mockData
.
createdBefor
e
,
group
:
currentGroup
,
stage
,
};
...
...
@@ -159,14 +157,6 @@ describe('EE Value Stream Analytics component', () => {
const
findPathNavigation
=
()
=>
wrapper
.
findComponent
(
PathNavigation
);
const
findStageTable
=
()
=>
wrapper
.
findComponent
(
StageTable
);
const
displaysProjectsDropdownFilter
=
(
flag
)
=>
{
expect
(
wrapper
.
findComponent
(
ProjectsDropdownFilter
).
exists
()).
toBe
(
flag
);
};
const
displaysDateRangePicker
=
(
flag
)
=>
{
expect
(
wrapper
.
findComponent
(
Daterange
).
exists
()).
toBe
(
flag
);
};
const
displaysMetrics
=
(
flag
)
=>
{
expect
(
wrapper
.
findComponent
(
Metrics
).
exists
()).
toBe
(
flag
);
};
...
...
@@ -187,8 +177,8 @@ describe('EE Value Stream Analytics component', () => {
expect
(
findPathNavigation
().
exists
()).
toBe
(
flag
);
};
const
displaysFilter
Bar
=
(
flag
)
=>
{
expect
(
wrapper
.
findComponent
(
FilterBar
).
exists
()).
toBe
(
flag
);
const
displaysFilter
s
=
(
flag
)
=>
{
expect
(
wrapper
.
findComponent
(
ValueStreamFilters
).
exists
()).
toBe
(
flag
);
};
const
displaysValueStreamSelect
=
(
flag
)
=>
{
...
...
@@ -215,14 +205,6 @@ describe('EE Value Stream Analytics component', () => {
expect
(
emptyState
.
props
(
'
svgPath
'
)).
toBe
(
emptyStateSvgPath
);
});
it
(
'
does not display the projects filter
'
,
()
=>
{
displaysProjectsDropdownFilter
(
false
);
});
it
(
'
does not display the date range picker
'
,
()
=>
{
displaysDateRangePicker
(
false
);
});
it
(
'
does not display the metrics cards
'
,
()
=>
{
displaysMetrics
(
false
);
});
...
...
@@ -263,14 +245,6 @@ describe('EE Value Stream Analytics component', () => {
expect
(
emptyState
.
props
(
'
svgPath
'
)).
toBe
(
noAccessSvgPath
);
});
it
(
'
does not display the projects filter
'
,
()
=>
{
displaysProjectsDropdownFilter
(
false
);
});
it
(
'
does not display the date range picker
'
,
()
=>
{
displaysDateRangePicker
(
false
);
});
it
(
'
does not display the metrics
'
,
()
=>
{
displaysMetrics
(
false
);
});
...
...
@@ -309,27 +283,12 @@ describe('EE Value Stream Analytics component', () => {
expect
(
wrapper
.
findComponent
(
GlEmptyState
).
exists
()).
toBe
(
false
);
});
it
(
'
displays the projects filter
'
,
()
=>
{
displaysProjectsDropdownFilter
(
true
);
expect
(
wrapper
.
findComponent
(
ProjectsDropdownFilter
).
props
()).
toEqual
(
expect
.
objectContaining
({
queryParams
:
wrapper
.
vm
.
projectsQueryParams
,
multiSelect
:
wrapper
.
vm
.
$options
.
multiProjectSelect
,
}),
);
});
it
(
'
displays the value stream select component
'
,
()
=>
{
displaysValueStreamSelect
(
true
);
});
it
(
'
displays the date range picker
'
,
()
=>
{
displaysDateRangePicker
(
true
);
});
it
(
'
displays the filter bar
'
,
()
=>
{
displaysFilter
Bar
(
true
);
displaysFilter
s
(
true
);
});
it
(
'
displays the metrics
'
,
()
=>
{
...
...
@@ -505,8 +464,8 @@ describe('EE Value Stream Analytics component', () => {
describe
(
'
Url parameters
'
,
()
=>
{
const
defaultParams
=
{
value_stream_id
:
selectedValueStream
.
id
,
created_after
:
toYmd
(
mockData
.
startDate
),
created_before
:
toYmd
(
mockData
.
endDat
e
),
created_after
:
toYmd
(
mockData
.
createdAfter
),
created_before
:
toYmd
(
mockData
.
createdBefor
e
),
stage_id
:
null
,
project_ids
:
null
,
sort
:
null
,
...
...
@@ -556,8 +515,8 @@ describe('EE Value Stream Analytics component', () => {
it
(
'
sets the value_stream_id url parameter
'
,
async
()
=>
{
await
shouldMergeUrlParams
(
wrapper
,
{
...
defaultParams
,
created_after
:
toYmd
(
mockData
.
startDate
),
created_before
:
toYmd
(
mockData
.
endDat
e
),
created_after
:
toYmd
(
mockData
.
createdAfter
),
created_before
:
toYmd
(
mockData
.
createdBefor
e
),
project_ids
:
null
,
});
});
...
...
@@ -573,8 +532,8 @@ describe('EE Value Stream Analytics component', () => {
it
(
'
sets the project_ids url parameter
'
,
async
()
=>
{
await
shouldMergeUrlParams
(
wrapper
,
{
...
defaultParams
,
created_after
:
toYmd
(
mockData
.
startDate
),
created_before
:
toYmd
(
mockData
.
endDat
e
),
created_after
:
toYmd
(
mockData
.
createdAfter
),
created_before
:
toYmd
(
mockData
.
createdBefor
e
),
project_ids
:
selectedProjectIds
,
stage_id
:
null
,
});
...
...
ee/spec/frontend/analytics/cycle_analytics/components/value_stream_filters_spec.js
0 → 100644
View file @
857d228b
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
FilterBar
from
'
ee/analytics/cycle_analytics/components/filter_bar.vue
'
;
import
ValueStreamFilters
from
'
ee/analytics/cycle_analytics/components/value_stream_filters.vue
'
;
import
Daterange
from
'
ee/analytics/shared/components/daterange.vue
'
;
import
ProjectsDropdownFilter
from
'
ee/analytics/shared/components/projects_dropdown_filter.vue
'
;
import
{
createdAfter
as
startDate
,
createdBefore
as
endDate
,
currentGroup
,
selectedProjects
,
}
from
'
../mock_data
'
;
function
createComponent
(
props
=
{})
{
return
shallowMount
(
ValueStreamFilters
,
{
propsData
:
{
selectedProjects
,
groupId
:
currentGroup
.
id
,
groupPath
:
currentGroup
.
fullPath
,
startDate
,
endDate
,
...
props
,
},
});
}
describe
(
'
ValueStreamFilters
'
,
()
=>
{
let
wrapper
;
const
findProjectsDropdown
=
()
=>
wrapper
.
findComponent
(
ProjectsDropdownFilter
);
const
findDateRangePicker
=
()
=>
wrapper
.
findComponent
(
Daterange
);
const
findFilterBar
=
()
=>
wrapper
.
findComponent
(
FilterBar
);
beforeEach
(()
=>
{
wrapper
=
createComponent
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
will render the filter bar
'
,
()
=>
{
expect
(
findFilterBar
().
exists
()).
toBe
(
true
);
});
it
(
'
will render the projects dropdown
'
,
()
=>
{
expect
(
findProjectsDropdown
().
exists
()).
toBe
(
true
);
expect
(
wrapper
.
findComponent
(
ProjectsDropdownFilter
).
props
()).
toEqual
(
expect
.
objectContaining
({
queryParams
:
wrapper
.
vm
.
projectsQueryParams
,
multiSelect
:
wrapper
.
vm
.
$options
.
multiProjectSelect
,
}),
);
});
it
(
'
will render the date range picker
'
,
()
=>
{
expect
(
findDateRangePicker
().
exists
()).
toBe
(
true
);
});
it
(
'
will emit `selectProject` when a project is selected
'
,
()
=>
{
findProjectsDropdown
().
vm
.
$emit
(
'
selected
'
);
expect
(
wrapper
.
emitted
(
'
selectProject
'
)).
not
.
toBeUndefined
();
});
it
(
'
will emit `setDateRange` when the date range changes
'
,
()
=>
{
findDateRangePicker
().
vm
.
$emit
(
'
change
'
);
expect
(
wrapper
.
emitted
(
'
setDateRange
'
)).
not
.
toBeUndefined
();
});
describe
(
'
hasDateRangeFilter = false
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
hasDateRangeFilter
:
false
});
});
it
(
'
will not render the date range picker
'
,
()
=>
{
expect
(
findDateRangePicker
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
hasProjectFilter = false
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
hasProjectFilter
:
false
});
});
it
(
'
will not render the project dropdown
'
,
()
=>
{
expect
(
findProjectsDropdown
().
exists
()).
toBe
(
false
);
});
});
});
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
View file @
857d228b
...
...
@@ -158,8 +158,8 @@ export const stageCounts = rawStageMedians.reduce((acc, { id, value }) => {
return
{
...
acc
,
[
stageId
]:
value
};
},
{});
export
const
endDat
e
=
new
Date
(
2019
,
0
,
14
);
export
const
startDate
=
getDateInPast
(
endDat
e
,
DEFAULT_DAYS_IN_PAST
);
export
const
createdBefor
e
=
new
Date
(
2019
,
0
,
14
);
export
const
createdAfter
=
getDateInPast
(
createdBefor
e
,
DEFAULT_DAYS_IN_PAST
);
export
const
issueEvents
=
deepCamelCase
(
stageFixtures
.
issue
);
export
const
planEvents
=
deepCamelCase
(
stageFixtures
.
plan
);
...
...
@@ -204,7 +204,7 @@ export const labelEndEvent = customStageLabelEvents.find(
(
ev
)
=>
ev
.
identifier
===
labelStartEvent
.
allowedEndEvents
[
0
],
);
const
dateRange
=
getDatesInRange
(
startDate
,
endDat
e
,
toYmd
);
const
dateRange
=
getDatesInRange
(
createdAfter
,
createdBefor
e
,
toYmd
);
export
const
apiTasksByTypeData
=
getJSONFixture
(
'
analytics/charts/type_of_work/tasks_by_type.json
'
,
...
...
ee/spec/frontend/analytics/cycle_analytics/store/actions_spec.js
View file @
857d228b
...
...
@@ -10,8 +10,8 @@ import httpStatusCodes from '~/lib/utils/http_status';
import
{
currentGroup
,
allowedStages
as
stages
,
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
customizableStagesAndEvents
,
endpoints
,
valueStreams
,
...
...
@@ -53,8 +53,8 @@ describe('Value Stream Analytics actions', () => {
beforeEach
(()
=>
{
state
=
{
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
stages
:
[],
featureFlags
:
{
hasDurationChart
:
true
,
...
...
@@ -269,7 +269,7 @@ describe('Value Stream Analytics actions', () => {
}
beforeEach
(()
=>
{
state
=
{
...
state
,
currentGroup
,
startDate
,
endDat
e
};
state
=
{
...
state
,
currentGroup
,
createdAfter
,
createdBefor
e
};
});
it
(
`dispatches actions for required value stream analytics analytics data`
,
()
=>
{
...
...
@@ -961,9 +961,9 @@ describe('Value Stream Analytics actions', () => {
});
describe
.
each
`
targetAction | payload | mutations
${
actions
.
setDateRange
}
|
${{
startDate
,
endDate
}
} |
${[{
type
:
'
SET_DATE_RANGE
'
,
payload
:
{
startDate
,
endDat
e
}
}]}
$
{
actions
.
setFilters
}
|
${
''
}
|
${[]}
targetAction | payload
| mutations
${
actions
.
setDateRange
}
|
${{
createdAfter
,
createdBefore
}
} |
${[{
type
:
'
SET_DATE_RANGE
'
,
payload
:
{
createdAfter
,
createdBefor
e
}
}]}
$
{
actions
.
setFilters
}
|
${
''
}
|
${[]}
`
(
'
$action
'
,
({
targetAction
,
payload
,
mutations
})
=>
{
let
stateWithOverview
=
null
;
...
...
ee/spec/frontend/analytics/cycle_analytics/store/getters_spec.js
View file @
857d228b
...
...
@@ -9,8 +9,8 @@ import {
getFilterValues
,
}
from
'
jest/vue_shared/components/filtered_search_bar/store/modules/filters/test_helper
'
;
import
{
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
allowedStages
,
selectedProjects
,
issueStage
,
...
...
@@ -97,8 +97,8 @@ describe('Value Stream Analytics getters', () => {
currentGroup
:
{
fullPath
,
},
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
selectedProjects
,
filters
:
{
authors
:
{
selected
:
selectedUserParams
[
0
]
},
...
...
ee/spec/frontend/analytics/cycle_analytics/store/modules/duration_chart/actions_spec.js
View file @
857d228b
...
...
@@ -10,8 +10,8 @@ import httpStatusCodes from '~/lib/utils/http_status';
import
{
group
,
allowedStages
as
stages
,
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
rawDurationData
,
transformedDurationData
,
endpoints
,
...
...
@@ -27,8 +27,8 @@ const [selectedValueStream] = valueStreams;
const
error
=
new
Error
(
`Request failed with status code
${
httpStatusCodes
.
BAD_REQUEST
}
`
);
const
rootState
=
{
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
stages
:
[...
activeStages
,
hiddenStage
],
selectedGroup
,
selectedValueStream
,
...
...
ee/spec/frontend/analytics/cycle_analytics/store/modules/duration_chart/getters_spec.js
View file @
857d228b
import
*
as
getters
from
'
ee/analytics/cycle_analytics/store/modules/duration_chart/getters
'
;
import
{
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
transformedDurationData
,
durationChartPlottableData
,
}
from
'
../../../mock_data
'
;
const
rootState
=
{
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
};
describe
(
'
DurationChart getters
'
,
()
=>
{
...
...
ee/spec/frontend/analytics/cycle_analytics/store/modules/type_of_work/actions_spec.js
View file @
857d228b
...
...
@@ -11,7 +11,13 @@ import * as types from 'ee/analytics/cycle_analytics/store/modules/type_of_work/
import
testAction
from
'
helpers/vuex_action_helper
'
;
import
createFlash
from
'
~/flash
'
;
import
httpStatusCodes
from
'
~/lib/utils/http_status
'
;
import
{
groupLabels
,
endpoints
,
startDate
,
endDate
,
rawTasksByTypeData
}
from
'
../../../mock_data
'
;
import
{
groupLabels
,
endpoints
,
createdAfter
,
createdBefore
,
rawTasksByTypeData
,
}
from
'
../../../mock_data
'
;
jest
.
mock
(
'
~/flash
'
);
...
...
@@ -33,7 +39,7 @@ describe('Type of work actions', () => {
...
rootGetters
,
...
getters
,
...
state
,
rootState
:
{
startDate
,
endDat
e
},
rootState
:
{
createdAfter
,
createdBefor
e
},
};
beforeEach
(()
=>
{
...
...
ee/spec/frontend/analytics/cycle_analytics/store/modules/type_of_work/getters_spec.js
View file @
857d228b
...
...
@@ -2,13 +2,13 @@ import { tasksByTypeChartData } from 'ee/analytics/cycle_analytics/store/modules
import
{
rawTasksByTypeData
,
transformedTasksByTypeData
,
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
}
from
'
../../../mock_data
'
;
describe
(
'
Type of work getters
'
,
()
=>
{
describe
(
'
tasksByTypeChartData
'
,
()
=>
{
const
rootState
=
{
startDate
,
endDat
e
};
const
rootState
=
{
createdAfter
,
createdBefor
e
};
describe
(
'
with data
'
,
()
=>
{
it
(
'
correctly transforms the raw task by type data
'
,
()
=>
{
expect
(
tasksByTypeChartData
(
rawTasksByTypeData
,
null
,
rootState
)).
toEqual
(
...
...
ee/spec/frontend/analytics/cycle_analytics/store/mutations_spec.js
View file @
857d228b
...
...
@@ -11,8 +11,8 @@ import {
codeStage
,
stagingStage
,
reviewStage
,
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
selectedProjects
,
customizableStagesAndEvents
,
valueStreams
,
...
...
@@ -91,7 +91,7 @@ describe('Value Stream Analytics mutations', () => {
mutation | payload | expectedState
${
types
.
SET_FEATURE_FLAGS
}
|
${{
hasDurationChart
:
true
}
} |
${{
featureFlags
:
{
hasDurationChart
:
true
}
}}
${
types
.
SET_SELECTED_PROJECTS
}
|
${
selectedProjects
}
|
${{
selectedProjects
}
}
${
types
.
SET_DATE_RANGE
}
|
${{
startDate
,
endDate
}
} |
${{
startDate
,
endDat
e
}
}
${
types
.
SET_DATE_RANGE
}
|
${{
createdAfter
,
createdBefore
}
} |
${{
createdAfter
,
createdBefor
e
}
}
${
types
.
SET_SELECTED_STAGE
}
|
${{
id
:
'
first-stage
'
}
} |
${{
selectedStage
:
{
id
:
'
first-stage
'
}
}}
${
types
.
RECEIVE_CREATE_VALUE_STREAM_ERROR
}
|
${
valueStreamErrors
}
|
${{
createValueStreamErrors
:
expectedValueStreamErrors
,
isCreatingValueStream
:
false
}
}
${
types
.
RECEIVE_UPDATE_VALUE_STREAM_ERROR
}
|
${
valueStreamErrors
}
|
${{
createValueStreamErrors
:
expectedValueStreamErrors
,
isEditingValueStream
:
false
}
}
...
...
@@ -235,8 +235,8 @@ describe('Value Stream Analytics mutations', () => {
stateKey | expectedState
${
'
isLoading
'
}
|
${
true
}
${
'
selectedProjects
'
}
|
${
initialData
.
selectedProjects
}
${
'
startDate
'
}
|
${
initialData
.
createdAfter
}
${
'
endDate
'
}
|
${
initialData
.
createdBefore
}
${
'
createdAfter
'
}
|
${
initialData
.
createdAfter
}
${
'
createdBefore
'
}
|
${
initialData
.
createdBefore
}
`
(
'
$stateKey will be set to $expectedState
'
,
({
stateKey
,
expectedState
})
=>
{
state
=
{};
mutations
[
types
.
INITIALIZE_VSA
](
state
,
initialData
);
...
...
ee/spec/frontend/analytics/cycle_analytics/utils_spec.js
View file @
857d228b
...
...
@@ -32,8 +32,8 @@ import {
transformedDurationData
,
flattenedDurationData
,
durationChartPlottableData
,
startDate
,
endDat
e
,
createdAfter
,
createdBefor
e
,
issueStage
,
rawCustomStage
,
rawTasksByTypeData
,
...
...
@@ -141,7 +141,11 @@ describe('Value Stream Analytics utils', () => {
describe
(
'
cycleAnalyticsDurationChart
'
,
()
=>
{
it
(
'
computes the plottable data as expected
'
,
()
=>
{
const
plottableData
=
getDurationChartData
(
transformedDurationData
,
startDate
,
endDate
);
const
plottableData
=
getDurationChartData
(
transformedDurationData
,
createdAfter
,
createdBefore
,
);
expect
(
plottableData
).
toStrictEqual
(
durationChartPlottableData
);
});
...
...
@@ -251,7 +255,7 @@ describe('Value Stream Analytics utils', () => {
describe
(
'
getTasksByTypeData
'
,
()
=>
{
let
transformed
=
{};
const
groupBy
=
getDatesInRange
(
startDate
,
endDat
e
,
toYmd
);
const
groupBy
=
getDatesInRange
(
createdAfter
,
createdBefor
e
,
toYmd
);
// only return the values, drop the date which is the first paramater
const
extractSeriesValues
=
({
label
:
{
title
:
name
},
series
})
=>
{
return
{
...
...
@@ -268,17 +272,23 @@ describe('Value Stream Analytics utils', () => {
});
it
(
'
will return blank arrays if given no data
'
,
()
=>
{
[{
data
:
[],
startDate
,
endDate
},
[],
{}].
forEach
((
chartData
)
=>
{
transformed
=
getTasksByTypeData
(
chartData
);
[
'
data
'
,
'
groupBy
'
].
forEach
((
key
)
=>
{
expect
(
transformed
[
key
]).
toEqual
([]);
});
});
[{
data
:
[],
startDate
:
createdAfter
,
endDate
:
createdBefore
},
[],
{}].
forEach
(
(
chartData
)
=>
{
transformed
=
getTasksByTypeData
(
chartData
);
[
'
data
'
,
'
groupBy
'
].
forEach
((
key
)
=>
{
expect
(
transformed
[
key
]).
toEqual
([]);
});
},
);
});
describe
(
'
with data
'
,
()
=>
{
beforeEach
(()
=>
{
transformed
=
getTasksByTypeData
({
data
:
rawTasksByTypeData
,
startDate
,
endDate
});
transformed
=
getTasksByTypeData
({
data
:
rawTasksByTypeData
,
startDate
:
createdAfter
,
endDate
:
createdBefore
,
});
});
it
(
'
will return an object with the properties needed for the chart
'
,
()
=>
{
...
...
@@ -293,11 +303,11 @@ describe('Value Stream Analytics utils', () => {
});
it
(
'
the start date is the first element
'
,
()
=>
{
expect
(
transformed
.
groupBy
[
0
]).
toEqual
(
toYmd
(
startDate
));
expect
(
transformed
.
groupBy
[
0
]).
toEqual
(
toYmd
(
createdAfter
));
});
it
(
'
the end date is the last element
'
,
()
=>
{
expect
(
transformed
.
groupBy
[
transformed
.
groupBy
.
length
-
1
]).
toEqual
(
toYmd
(
endDat
e
));
expect
(
transformed
.
groupBy
[
transformed
.
groupBy
.
length
-
1
]).
toEqual
(
toYmd
(
createdBefor
e
));
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment