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
41ee917d
Commit
41ee917d
authored
Apr 28, 2021
by
Ezekiel Kigbo
Committed by
Nicolò Maria Mezzopera
Apr 28, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[VSA] Enable pagination (frontend)
parent
3c69043c
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
236 additions
and
48 deletions
+236
-48
ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
...javascripts/analytics/cycle_analytics/components/base.vue
+8
-2
ee/app/assets/javascripts/analytics/cycle_analytics/components/stage_table_new.vue
.../analytics/cycle_analytics/components/stage_table_new.vue
+30
-6
ee/app/assets/javascripts/analytics/cycle_analytics/constants.js
...assets/javascripts/analytics/cycle_analytics/constants.js
+3
-0
ee/app/assets/javascripts/analytics/cycle_analytics/store/actions.js
...ts/javascripts/analytics/cycle_analytics/store/actions.js
+29
-7
ee/app/assets/javascripts/analytics/cycle_analytics/store/getters.js
...ts/javascripts/analytics/cycle_analytics/store/getters.js
+12
-1
ee/app/assets/javascripts/analytics/cycle_analytics/store/mutation_types.js
...scripts/analytics/cycle_analytics/store/mutation_types.js
+1
-0
ee/app/assets/javascripts/analytics/cycle_analytics/store/mutations.js
.../javascripts/analytics/cycle_analytics/store/mutations.js
+3
-0
ee/app/assets/javascripts/analytics/cycle_analytics/store/state.js
...sets/javascripts/analytics/cycle_analytics/store/state.js
+5
-0
ee/changelogs/unreleased/12524-vsa-enable-pagination-frontend.yml
...elogs/unreleased/12524-vsa-enable-pagination-frontend.yml
+5
-0
ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js
...rontend/analytics/cycle_analytics/components/base_spec.js
+4
-4
ee/spec/frontend/analytics/cycle_analytics/components/stage_table_new_spec.js
...lytics/cycle_analytics/components/stage_table_new_spec.js
+47
-8
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
+9
-0
ee/spec/frontend/analytics/cycle_analytics/store/actions_spec.js
.../frontend/analytics/cycle_analytics/store/actions_spec.js
+54
-19
ee/spec/frontend/analytics/cycle_analytics/store/getters_spec.js
.../frontend/analytics/cycle_analytics/store/getters_spec.js
+22
-0
ee/spec/frontend/analytics/cycle_analytics/store/mutations_spec.js
...rontend/analytics/cycle_analytics/store/mutations_spec.js
+3
-0
ee/spec/lib/gitlab/analytics/cycle_analytics/request_params_spec.rb
...b/gitlab/analytics/cycle_analytics/request_params_spec.rb
+1
-1
No files found.
ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
View file @
41ee917d
...
@@ -69,6 +69,7 @@ export default {
...
@@ -69,6 +69,7 @@ export default {
'
isLoadingValueStreams
'
,
'
isLoadingValueStreams
'
,
'
selectedStageError
'
,
'
selectedStageError
'
,
'
selectedValueStream
'
,
'
selectedValueStream
'
,
'
pagination
'
,
]),
]),
// NOTE: formEvents are fetched in the same request as the list of stages (fetchGroupStagesAndEvents)
// NOTE: formEvents are fetched in the same request as the list of stages (fetchGroupStagesAndEvents)
// so i think its ok to bind formEvents here even though its only used as a prop to the custom-stage-form
// so i think its ok to bind formEvents here even though its only used as a prop to the custom-stage-form
...
@@ -156,6 +157,7 @@ export default {
...
@@ -156,6 +157,7 @@ export default {
'
removeStage
'
,
'
removeStage
'
,
'
updateStage
'
,
'
updateStage
'
,
'
reorderStage
'
,
'
reorderStage
'
,
'
updateStageTablePagination
'
,
]),
]),
...
mapActions
(
'
customStages
'
,
[
'
hideForm
'
,
'
showCreateForm
'
,
'
showEditForm
'
,
'
createStage
'
]),
...
mapActions
(
'
customStages
'
,
[
'
hideForm
'
,
'
showCreateForm
'
,
'
showEditForm
'
,
'
createStage
'
]),
onProjectsSelect
(
projects
)
{
onProjectsSelect
(
projects
)
{
...
@@ -190,9 +192,11 @@ export default {
...
@@ -190,9 +192,11 @@ export default {
onStageReorder
(
data
)
{
onStageReorder
(
data
)
{
this
.
reorderStage
(
data
);
this
.
reorderStage
(
data
);
},
},
onHandleSelectPage
(
data
)
{
this
.
updateStageTablePagination
(
data
);
},
},
},
multiProjectSelect
:
true
,
multiProjectSelect
:
true
,
dateOptions
:
[
7
,
30
,
90
],
maxDateRange
:
DATE_RANGE_LIMIT
,
maxDateRange
:
DATE_RANGE_LIMIT
,
};
};
</
script
>
</
script
>
...
@@ -279,9 +283,11 @@ export default {
...
@@ -279,9 +283,11 @@ export default {
v-if=
"!isLoading && !isOverviewStageSelected"
v-if=
"!isLoading && !isOverviewStageSelected"
:is-loading=
"isLoading || isLoadingStage"
:is-loading=
"isLoading || isLoadingStage"
:stage-events=
"currentStageEvents"
:stage-events=
"currentStageEvents"
:
current
-stage=
"selectedStage"
:
selected
-stage=
"selectedStage"
:empty-state-message=
"selectedStageError"
:empty-state-message=
"selectedStageError"
:no-data-svg-path=
"noDataSvgPath"
:no-data-svg-path=
"noDataSvgPath"
:pagination=
"pagination"
@
handleSelectPage=
"onHandleSelectPage"
/>
/>
</
template
>
</
template
>
<stage-table
<stage-table
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/components/stage_table_new.vue
View file @
41ee917d
<
script
>
<
script
>
import
{
GlEmptyState
,
GlIcon
,
GlLink
,
GlLoadingIcon
,
GlTable
}
from
'
@gitlab/ui
'
;
import
{
GlEmptyState
,
GlIcon
,
GlLink
,
GlLoadingIcon
,
Gl
Pagination
,
Gl
Table
}
from
'
@gitlab/ui
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
NOT_ENOUGH_DATA_ERROR
}
from
'
../constants
'
;
import
{
NOT_ENOUGH_DATA_ERROR
}
from
'
../constants
'
;
import
TotalTime
from
'
./total_time_component.vue
'
;
import
TotalTime
from
'
./total_time_component.vue
'
;
...
@@ -19,11 +19,12 @@ export default {
...
@@ -19,11 +19,12 @@ export default {
GlIcon
,
GlIcon
,
GlLink
,
GlLink
,
GlLoadingIcon
,
GlLoadingIcon
,
GlPagination
,
GlTable
,
GlTable
,
TotalTime
,
TotalTime
,
},
},
props
:
{
props
:
{
current
Stage
:
{
selected
Stage
:
{
type
:
Object
,
type
:
Object
,
required
:
true
,
required
:
true
,
},
},
...
@@ -44,6 +45,10 @@ export default {
...
@@ -44,6 +45,10 @@ export default {
required
:
false
,
required
:
false
,
default
:
''
,
default
:
''
,
},
},
pagination
:
{
type
:
Object
,
required
:
true
,
},
},
},
computed
:
{
computed
:
{
isEmptyStage
()
{
isEmptyStage
()
{
...
@@ -54,12 +59,12 @@ export default {
...
@@ -54,12 +59,12 @@ export default {
return
emptyStateMessage
||
NOT_ENOUGH_DATA_ERROR
;
return
emptyStateMessage
||
NOT_ENOUGH_DATA_ERROR
;
},
},
isDefaultTestStage
()
{
isDefaultTestStage
()
{
const
{
current
Stage
}
=
this
;
const
{
selected
Stage
}
=
this
;
return
!
currentStage
.
custom
&&
current
Stage
.
title
?.
toLowerCase
().
trim
()
===
'
test
'
;
return
!
selectedStage
.
custom
&&
selected
Stage
.
title
?.
toLowerCase
().
trim
()
===
'
test
'
;
},
},
isDefaultStagingStage
()
{
isDefaultStagingStage
()
{
const
{
current
Stage
}
=
this
;
const
{
selected
Stage
}
=
this
;
return
!
currentStage
.
custom
&&
current
Stage
.
title
?.
toLowerCase
().
trim
()
===
'
staging
'
;
return
!
selectedStage
.
custom
&&
selected
Stage
.
title
?.
toLowerCase
().
trim
()
===
'
staging
'
;
},
},
isMergeRequestStage
()
{
isMergeRequestStage
()
{
const
[
firstEvent
]
=
this
.
stageEvents
;
const
[
firstEvent
]
=
this
.
stageEvents
;
...
@@ -78,6 +83,12 @@ export default {
...
@@ -78,6 +83,12 @@ export default {
fields
()
{
fields
()
{
return
[
this
.
workflowTitle
,
{
key
:
'
time
'
,
label
:
__
(
'
Time
'
),
thClass
:
'
gl-w-half
'
}];
return
[
this
.
workflowTitle
,
{
key
:
'
time
'
,
label
:
__
(
'
Time
'
),
thClass
:
'
gl-w-half
'
}];
},
},
prevPage
()
{
return
Math
.
max
(
this
.
pagination
.
page
-
1
,
0
);
},
nextPage
()
{
return
this
.
pagination
.
hasNextPage
?
this
.
pagination
.
page
+
1
:
null
;
},
},
},
methods
:
{
methods
:
{
isMrLink
(
url
=
''
)
{
isMrLink
(
url
=
''
)
{
...
@@ -86,6 +97,9 @@ export default {
...
@@ -86,6 +97,9 @@ export default {
itemTitle
(
item
)
{
itemTitle
(
item
)
{
return
item
.
title
||
item
.
name
;
return
item
.
title
||
item
.
name
;
},
},
onSelectPage
(
page
)
{
this
.
$emit
(
'
handleSelectPage
'
,
{
page
});
},
},
},
};
};
</
script
>
</
script
>
...
@@ -194,5 +208,15 @@ export default {
...
@@ -194,5 +208,15 @@ export default {
<total-time
:time=
"item.totalTime"
data-testid=
"vsa-stage-event-time"
/>
<total-time
:time=
"item.totalTime"
data-testid=
"vsa-stage-event-time"
/>
</
template
>
</
template
>
</gl-table>
</gl-table>
<gl-pagination
v-if=
"!isLoading"
:value=
"pagination.page"
:prev-page=
"prevPage"
:next-page=
"nextPage"
align=
"center"
class=
"gl-mt-3"
data-testid=
"vsa-stage-pagination"
@
input=
"onSelectPage"
/>
</div>
</div>
</template>
</template>
ee/app/assets/javascripts/analytics/cycle_analytics/constants.js
View file @
41ee917d
...
@@ -73,3 +73,6 @@ export const OVERVIEW_STAGE_CONFIG = {
...
@@ -73,3 +73,6 @@ export const OVERVIEW_STAGE_CONFIG = {
export
const
NOT_ENOUGH_DATA_ERROR
=
s__
(
export
const
NOT_ENOUGH_DATA_ERROR
=
s__
(
"
ValueStreamAnalyticsStage|We don't have enough data to show this stage.
"
,
"
ValueStreamAnalyticsStage|We don't have enough data to show this stage.
"
,
);
);
export
const
PAGINATION_TYPE
=
'
keyset
'
;
export
const
PAGINATION_SORT_FIELD
=
'
created_at
'
;
ee/app/assets/javascripts/analytics/cycle_analytics/store/actions.js
View file @
41ee917d
import
Api
from
'
ee/api
'
;
import
Api
from
'
ee/api
'
;
import
createFlash
from
'
~/flash
'
;
import
createFlash
from
'
~/flash
'
;
import
{
normalizeHeaders
,
parseIntPagination
}
from
'
~/lib/utils/common_utils
'
;
import
httpStatus
from
'
~/lib/utils/http_status
'
;
import
httpStatus
from
'
~/lib/utils/http_status
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
import
{
FETCH_VALUE_STREAM_DATA
,
OVERVIEW_STAGE_CONFIG
}
from
'
../constants
'
;
import
{
FETCH_VALUE_STREAM_DATA
,
OVERVIEW_STAGE_CONFIG
}
from
'
../constants
'
;
...
@@ -30,7 +31,10 @@ export const setFeatureFlags = ({ commit }, featureFlags) =>
...
@@ -30,7 +31,10 @@ export const setFeatureFlags = ({ commit }, featureFlags) =>
export
const
setSelectedProjects
=
({
commit
},
projects
)
=>
export
const
setSelectedProjects
=
({
commit
},
projects
)
=>
commit
(
types
.
SET_SELECTED_PROJECTS
,
projects
);
commit
(
types
.
SET_SELECTED_PROJECTS
,
projects
);
export
const
setSelectedStage
=
({
commit
},
stage
)
=>
commit
(
types
.
SET_SELECTED_STAGE
,
stage
);
export
const
setSelectedStage
=
({
commit
},
stage
)
=>
{
commit
(
types
.
SET_SELECTED_STAGE
,
stage
);
commit
(
types
.
SET_PAGINATION
,
{
page
:
1
,
hasNextPage
:
null
});
};
export
const
setDateRange
=
({
commit
,
dispatch
},
{
skipFetch
=
false
,
startDate
,
endDate
})
=>
{
export
const
setDateRange
=
({
commit
,
dispatch
},
{
skipFetch
=
false
,
startDate
,
endDate
})
=>
{
commit
(
types
.
SET_DATE_RANGE
,
{
startDate
,
endDate
});
commit
(
types
.
SET_DATE_RANGE
,
{
startDate
,
endDate
});
...
@@ -41,8 +45,6 @@ export const setDateRange = ({ commit, dispatch }, { skipFetch = false, startDat
...
@@ -41,8 +45,6 @@ export const setDateRange = ({ commit, dispatch }, { skipFetch = false, startDat
};
};
export
const
requestStageData
=
({
commit
})
=>
commit
(
types
.
REQUEST_STAGE_DATA
);
export
const
requestStageData
=
({
commit
})
=>
commit
(
types
.
REQUEST_STAGE_DATA
);
export
const
receiveStageDataSuccess
=
({
commit
},
data
)
=>
commit
(
types
.
RECEIVE_STAGE_DATA_SUCCESS
,
data
);
export
const
receiveStageDataError
=
({
commit
},
error
)
=>
{
export
const
receiveStageDataError
=
({
commit
},
error
)
=>
{
const
{
message
=
''
}
=
error
;
const
{
message
=
''
}
=
error
;
...
@@ -53,18 +55,30 @@ export const receiveStageDataError = ({ commit }, error) => {
...
@@ -53,18 +55,30 @@ export const receiveStageDataError = ({ commit }, error) => {
commit
(
types
.
RECEIVE_STAGE_DATA_ERROR
,
message
);
commit
(
types
.
RECEIVE_STAGE_DATA_ERROR
,
message
);
};
};
export
const
fetchStageData
=
({
dispatch
,
getters
},
stageId
)
=>
{
export
const
fetchStageData
=
({
dispatch
,
getters
,
commit
},
stageId
)
=>
{
const
{
cycleAnalyticsRequestParams
=
{},
currentValueStreamId
,
currentGroupPath
}
=
getters
;
const
{
cycleAnalyticsRequestParams
=
{},
currentValueStreamId
,
currentGroupPath
,
paginationParams
,
}
=
getters
;
dispatch
(
'
requestStageData
'
);
dispatch
(
'
requestStageData
'
);
return
Api
.
cycleAnalyticsStageEvents
({
return
Api
.
cycleAnalyticsStageEvents
({
groupId
:
currentGroupPath
,
groupId
:
currentGroupPath
,
valueStreamId
:
currentValueStreamId
,
valueStreamId
:
currentValueStreamId
,
stageId
,
stageId
,
params
:
cycleAnalyticsRequestParams
,
params
:
{
...
cycleAnalyticsRequestParams
,
...
paginationParams
,
},
})
})
.
then
(
checkForDataError
)
.
then
(
checkForDataError
)
.
then
(({
data
})
=>
dispatch
(
'
receiveStageDataSuccess
'
,
data
))
.
then
(({
data
,
headers
})
=>
{
const
{
page
=
null
,
nextPage
=
null
}
=
parseIntPagination
(
normalizeHeaders
(
headers
));
commit
(
types
.
RECEIVE_STAGE_DATA_SUCCESS
,
data
);
commit
(
types
.
SET_PAGINATION
,
{
page
,
hasNextPage
:
Boolean
(
nextPage
)
});
})
.
catch
((
error
)
=>
dispatch
(
'
receiveStageDataError
'
,
error
));
.
catch
((
error
)
=>
dispatch
(
'
receiveStageDataError
'
,
error
));
};
};
...
@@ -466,3 +480,11 @@ export const fetchValueStreams = ({ commit, dispatch, getters }) => {
...
@@ -466,3 +480,11 @@ export const fetchValueStreams = ({ commit, dispatch, getters }) => {
export
const
setFilters
=
({
dispatch
})
=>
{
export
const
setFilters
=
({
dispatch
})
=>
{
return
dispatch
(
'
fetchCycleAnalyticsData
'
);
return
dispatch
(
'
fetchCycleAnalyticsData
'
);
};
};
export
const
updateStageTablePagination
=
(
{
commit
,
dispatch
,
state
:
{
selectedStage
}
},
{
page
},
)
=>
{
commit
(
types
.
SET_PAGINATION
,
{
page
});
return
dispatch
(
'
fetchStageData
'
,
selectedStage
.
id
);
};
ee/app/assets/javascripts/analytics/cycle_analytics/store/getters.js
View file @
41ee917d
...
@@ -4,7 +4,12 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
...
@@ -4,7 +4,12 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import
httpStatus
from
'
~/lib/utils/http_status
'
;
import
httpStatus
from
'
~/lib/utils/http_status
'
;
import
{
filterToQueryObject
}
from
'
~/vue_shared/components/filtered_search_bar/filtered_search_utils
'
;
import
{
filterToQueryObject
}
from
'
~/vue_shared/components/filtered_search_bar/filtered_search_utils
'
;
import
{
dateFormats
}
from
'
../../shared/constants
'
;
import
{
dateFormats
}
from
'
../../shared/constants
'
;
import
{
DEFAULT_VALUE_STREAM_ID
,
OVERVIEW_STAGE_CONFIG
}
from
'
../constants
'
;
import
{
DEFAULT_VALUE_STREAM_ID
,
OVERVIEW_STAGE_CONFIG
,
PAGINATION_TYPE
,
PAGINATION_SORT_FIELD
,
}
from
'
../constants
'
;
import
{
transformStagesForPathNavigation
}
from
'
../utils
'
;
import
{
transformStagesForPathNavigation
}
from
'
../utils
'
;
export
const
hasNoAccessError
=
(
state
)
=>
state
.
errorCode
===
httpStatus
.
FORBIDDEN
;
export
const
hasNoAccessError
=
(
state
)
=>
state
.
errorCode
===
httpStatus
.
FORBIDDEN
;
...
@@ -44,6 +49,12 @@ export const cycleAnalyticsRequestParams = (state, getters) => {
...
@@ -44,6 +49,12 @@ export const cycleAnalyticsRequestParams = (state, getters) => {
};
};
};
};
export
const
paginationParams
=
({
pagination
:
{
page
}
})
=>
({
pagination
:
PAGINATION_TYPE
,
sort
:
PAGINATION_SORT_FIELD
,
page
,
});
const
filterStagesByHiddenStatus
=
(
stages
=
[],
isHidden
=
true
)
=>
const
filterStagesByHiddenStatus
=
(
stages
=
[],
isHidden
=
true
)
=>
stages
.
filter
(({
hidden
=
false
})
=>
hidden
===
isHidden
);
stages
.
filter
(({
hidden
=
false
})
=>
hidden
===
isHidden
);
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/mutation_types.js
View file @
41ee917d
...
@@ -4,6 +4,7 @@ export const SET_SELECTED_PROJECTS = 'SET_SELECTED_PROJECTS';
...
@@ -4,6 +4,7 @@ export const SET_SELECTED_PROJECTS = 'SET_SELECTED_PROJECTS';
export
const
SET_SELECTED_STAGE
=
'
SET_SELECTED_STAGE
'
;
export
const
SET_SELECTED_STAGE
=
'
SET_SELECTED_STAGE
'
;
export
const
SET_DATE_RANGE
=
'
SET_DATE_RANGE
'
;
export
const
SET_DATE_RANGE
=
'
SET_DATE_RANGE
'
;
export
const
SET_SELECTED_VALUE_STREAM
=
'
SET_SELECTED_VALUE_STREAM
'
;
export
const
SET_SELECTED_VALUE_STREAM
=
'
SET_SELECTED_VALUE_STREAM
'
;
export
const
SET_PAGINATION
=
'
SET_PAGINATION
'
;
export
const
REQUEST_VALUE_STREAM_DATA
=
'
REQUEST_VALUE_STREAM_DATA
'
;
export
const
REQUEST_VALUE_STREAM_DATA
=
'
REQUEST_VALUE_STREAM_DATA
'
;
export
const
RECEIVE_VALUE_STREAM_DATA_SUCCESS
=
'
RECEIVE_VALUE_STREAM_DATA_SUCCESS
'
;
export
const
RECEIVE_VALUE_STREAM_DATA_SUCCESS
=
'
RECEIVE_VALUE_STREAM_DATA_SUCCESS
'
;
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/mutations.js
View file @
41ee917d
...
@@ -183,4 +183,7 @@ export default {
...
@@ -183,4 +183,7 @@ export default {
return
aName
.
toUpperCase
()
>
bName
.
toUpperCase
()
?
1
:
-
1
;
return
aName
.
toUpperCase
()
>
bName
.
toUpperCase
()
?
1
:
-
1
;
});
});
},
},
[
types
.
SET_PAGINATION
](
state
,
{
page
,
hasNextPage
})
{
state
.
pagination
=
{
page
,
hasNextPage
};
},
};
};
ee/app/assets/javascripts/analytics/cycle_analytics/store/state.js
View file @
41ee917d
...
@@ -34,4 +34,9 @@ export default () => ({
...
@@ -34,4 +34,9 @@ export default () => ({
summary
:
[],
summary
:
[],
medians
:
{},
medians
:
{},
valueStreams
:
[],
valueStreams
:
[],
pagination
:
{
page
:
null
,
hasNextPage
:
false
,
},
});
});
ee/changelogs/unreleased/12524-vsa-enable-pagination-frontend.yml
0 → 100644
View file @
41ee917d
---
title
:
Add pagination to the VSA stage table
merge_request
:
59650
author
:
type
:
changed
ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js
View file @
41ee917d
...
@@ -144,10 +144,10 @@ describe('Value Stream Analytics component', () => {
...
@@ -144,10 +144,10 @@ describe('Value Stream Analytics component', () => {
});
});
if
(
withStageSelected
)
{
if
(
withStageSelected
)
{
await
Promise
.
all
([
await
store
.
dispatch
(
store
.
dispatch
(
'
receiveGroupStagesSuccess
'
,
mockData
.
customizableStagesAndEvents
.
stages
)
,
'
receiveGroupStagesSuccess
'
,
store
.
dispatch
(
'
receiveStageDataSuccess
'
,
mockData
.
issueEvents
)
,
mockData
.
customizableStagesAndEvents
.
stages
,
]
);
);
}
}
return
comp
;
return
comp
;
}
}
...
...
ee/spec/frontend/analytics/cycle_analytics/components/stage_table_new_spec.js
View file @
41ee917d
...
@@ -22,8 +22,10 @@ const [firstIssueEvent] = issueEvents;
...
@@ -22,8 +22,10 @@ const [firstIssueEvent] = issueEvents;
const
[
firstStagingEvent
]
=
stagingEvents
;
const
[
firstStagingEvent
]
=
stagingEvents
;
const
[
firstTestEvent
]
=
testEvents
;
const
[
firstTestEvent
]
=
testEvents
;
const
[
firstReviewEvent
]
=
reviewEvents
;
const
[
firstReviewEvent
]
=
reviewEvents
;
const
pagination
=
{
page
:
1
,
hasNextPage
:
true
};
const
findStageEvents
=
()
=>
wrapper
.
findAllByTestId
(
'
vsa-stage-event
'
);
const
findStageEvents
=
()
=>
wrapper
.
findAllByTestId
(
'
vsa-stage-event
'
);
const
findPagination
=
()
=>
wrapper
.
findByTestId
(
'
vsa-stage-pagination
'
);
const
findStageEventTitle
=
(
ev
)
=>
extendedWrapper
(
ev
).
findByTestId
(
'
vsa-stage-event-title
'
);
const
findStageEventTitle
=
(
ev
)
=>
extendedWrapper
(
ev
).
findByTestId
(
'
vsa-stage-event-title
'
);
function
createComponent
(
props
=
{},
shallow
=
false
)
{
function
createComponent
(
props
=
{},
shallow
=
false
)
{
...
@@ -34,7 +36,8 @@ function createComponent(props = {}, shallow = false) {
...
@@ -34,7 +36,8 @@ function createComponent(props = {}, shallow = false) {
isLoading
:
false
,
isLoading
:
false
,
stageEvents
:
issueEvents
,
stageEvents
:
issueEvents
,
noDataSvgPath
,
noDataSvgPath
,
currentStage
:
issueStage
,
selectedStage
:
issueStage
,
pagination
,
...
props
,
...
props
,
},
},
stubs
:
{
stubs
:
{
...
@@ -90,7 +93,7 @@ describe('StageTable', () => {
...
@@ -90,7 +93,7 @@ describe('StageTable', () => {
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
wrapper
=
createComponent
({
stageEvents
:
[{
...
firstIssueEvent
}],
stageEvents
:
[{
...
firstIssueEvent
}],
current
Stage
:
{
...
issueStage
,
custom
:
false
},
selected
Stage
:
{
...
issueStage
,
custom
:
false
},
});
});
});
});
...
@@ -131,7 +134,7 @@ describe('StageTable', () => {
...
@@ -131,7 +134,7 @@ describe('StageTable', () => {
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
wrapper
=
createComponent
({
stageEvents
:
[{
...
firstReviewEvent
}],
stageEvents
:
[{
...
firstReviewEvent
}],
current
Stage
:
{
...
reviewStage
,
custom
:
false
},
selected
Stage
:
{
...
reviewStage
,
custom
:
false
},
});
});
});
});
...
@@ -145,7 +148,7 @@ describe('StageTable', () => {
...
@@ -145,7 +148,7 @@ describe('StageTable', () => {
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
wrapper
=
createComponent
({
stageEvents
:
[{
...
firstStagingEvent
}],
stageEvents
:
[{
...
firstStagingEvent
}],
current
Stage
:
{
...
stagingStage
,
custom
:
false
},
selected
Stage
:
{
...
stagingStage
,
custom
:
false
},
});
});
});
});
...
@@ -187,7 +190,7 @@ describe('StageTable', () => {
...
@@ -187,7 +190,7 @@ describe('StageTable', () => {
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
wrapper
=
createComponent
({
stageEvents
:
[{
...
firstTestEvent
}],
stageEvents
:
[{
...
firstTestEvent
}],
current
Stage
:
{
...
testStage
,
custom
:
false
},
selected
Stage
:
{
...
testStage
,
custom
:
false
},
});
});
});
});
...
@@ -234,9 +237,18 @@ describe('StageTable', () => {
...
@@ -234,9 +237,18 @@ describe('StageTable', () => {
});
});
});
});
it
(
'
isLoading = true
'
,
()
=>
{
describe
(
'
isLoading = true
'
,
()
=>
{
wrapper
=
createComponent
({
isLoading
:
true
},
true
);
beforeEach
(()
=>
{
expect
(
wrapper
.
find
(
GlLoadingIcon
).
exists
()).
toEqual
(
true
);
wrapper
=
createComponent
({
isLoading
:
true
},
true
);
});
it
(
'
will display the loading icon
'
,
()
=>
{
expect
(
wrapper
.
find
(
GlLoadingIcon
).
exists
()).
toBe
(
true
);
});
it
(
'
will not display pagination
'
,
()
=>
{
expect
(
findPagination
().
exists
()).
toBe
(
false
);
});
});
});
describe
(
'
with no stageEvents
'
,
()
=>
{
describe
(
'
with no stageEvents
'
,
()
=>
{
...
@@ -263,4 +275,31 @@ describe('StageTable', () => {
...
@@ -263,4 +275,31 @@ describe('StageTable', () => {
expect
(
wrapper
.
html
()).
toContain
(
emptyStateMessage
);
expect
(
wrapper
.
html
()).
toContain
(
emptyStateMessage
);
});
});
});
});
describe
(
'
Pagination
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
();
});
it
(
'
will display the pagination component
'
,
()
=>
{
expect
(
findPagination
().
exists
()).
toBe
(
true
);
});
it
(
'
clicking prev or next will emit an event
'
,
async
()
=>
{
findPagination
().
vm
.
$emit
(
'
input
'
,
2
);
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
emitted
(
'
handleSelectPage
'
)[
0
]).
toEqual
([{
page
:
2
}]);
});
describe
(
'
with `hasNextPage=false
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
pagination
:
{
page
:
1
,
hasNextPage
:
false
}
});
});
it
(
'
will not display the pagination component
'
,
()
=>
{
expect
(
findPagination
().
exists
()).
toBe
(
false
);
});
});
});
});
});
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
View file @
41ee917d
...
@@ -3,6 +3,8 @@ import {
...
@@ -3,6 +3,8 @@ import {
DEFAULT_DAYS_IN_PAST
,
DEFAULT_DAYS_IN_PAST
,
TASKS_BY_TYPE_SUBJECT_ISSUE
,
TASKS_BY_TYPE_SUBJECT_ISSUE
,
OVERVIEW_STAGE_CONFIG
,
OVERVIEW_STAGE_CONFIG
,
PAGINATION_TYPE
,
PAGINATION_SORT_FIELD
,
}
from
'
ee/analytics/cycle_analytics/constants
'
;
}
from
'
ee/analytics/cycle_analytics/constants
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/mutation_types
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/mutation_types
'
;
import
mutations
from
'
ee/analytics/cycle_analytics/store/mutations
'
;
import
mutations
from
'
ee/analytics/cycle_analytics/store/mutations
'
;
...
@@ -302,3 +304,10 @@ export const selectedProjects = [
...
@@ -302,3 +304,10 @@ export const selectedProjects = [
];
];
export
const
pathNavIssueMetric
=
172800
;
export
const
pathNavIssueMetric
=
172800
;
export
const
initialPaginationState
=
{
page
:
null
,
hasNextPage
:
false
};
export
const
basePaginationResult
=
{
pagination
:
PAGINATION_TYPE
,
sort
:
PAGINATION_SORT_FIELD
,
page
:
null
,
};
ee/spec/frontend/analytics/cycle_analytics/store/actions_spec.js
View file @
41ee917d
...
@@ -78,7 +78,6 @@ describe('Value Stream Analytics actions', () => {
...
@@ -78,7 +78,6 @@ describe('Value Stream Analytics actions', () => {
action | type | stateKey | payload
action | type | stateKey | payload
${
'
setFeatureFlags
'
}
|
${
'
SET_FEATURE_FLAGS
'
}
|
${
'
featureFlags
'
}
|
${{
hasDurationChart
:
true
}
}
${
'
setFeatureFlags
'
}
|
${
'
SET_FEATURE_FLAGS
'
}
|
${
'
featureFlags
'
}
|
${{
hasDurationChart
:
true
}
}
${
'
setSelectedProjects
'
}
|
${
'
SET_SELECTED_PROJECTS
'
}
|
${
'
selectedProjectIds
'
}
|
${[
10
,
20
,
30
,
40
]}
${
'
setSelectedProjects
'
}
|
${
'
SET_SELECTED_PROJECTS
'
}
|
${
'
selectedProjectIds
'
}
|
${[
10
,
20
,
30
,
40
]}
${
'
setSelectedStage
'
}
|
${
'
SET_SELECTED_STAGE
'
}
|
${
'
selectedStage
'
}
|
${{
id
:
'
someStageId
'
}
}
`
(
'
$action should set $stateKey with $payload and type $type
'
,
({
action
,
type
,
payload
})
=>
{
`
(
'
$action should set $stateKey with $payload and type $type
'
,
({
action
,
type
,
payload
})
=>
{
return
testAction
(
return
testAction
(
actions
[
action
],
actions
[
action
],
...
@@ -94,6 +93,18 @@ describe('Value Stream Analytics actions', () => {
...
@@ -94,6 +93,18 @@ describe('Value Stream Analytics actions', () => {
);
);
});
});
describe
(
'
setSelectedStage
'
,
()
=>
{
const
data
=
{
id
:
'
someStageId
'
};
const
payload
=
{
hasNextPage
:
null
,
page
:
1
};
it
(
`dispatches the
${
types
.
SET_SELECTED_STAGE
}
and
${
types
.
SET_PAGINATION
}
actions`
,
()
=>
{
return
testAction
(
actions
.
setSelectedStage
,
data
,
{
...
state
,
selectedValueStream
:
{}
},
[
{
type
:
types
.
SET_SELECTED_STAGE
,
payload
:
data
},
{
type
:
types
.
SET_PAGINATION
,
payload
},
]);
});
});
describe
(
'
setSelectedValueStream
'
,
()
=>
{
describe
(
'
setSelectedValueStream
'
,
()
=>
{
const
vs
=
{
id
:
'
vs-1
'
,
name
:
'
Value stream 1
'
};
const
vs
=
{
id
:
'
vs-1
'
,
name
:
'
Value stream 1
'
};
...
@@ -144,28 +155,64 @@ describe('Value Stream Analytics actions', () => {
...
@@ -144,28 +155,64 @@ describe('Value Stream Analytics actions', () => {
});
});
describe
(
'
fetchStageData
'
,
()
=>
{
describe
(
'
fetchStageData
'
,
()
=>
{
const
headers
=
{
'
X-Next-Page
'
:
2
,
'
X-Page
'
:
1
,
};
beforeEach
(()
=>
{
beforeEach
(()
=>
{
state
=
{
...
state
,
currentGroup
};
state
=
{
...
state
,
currentGroup
};
mock
=
new
MockAdapter
(
axios
);
mock
=
new
MockAdapter
(
axios
);
mock
.
onGet
(
endpoints
.
stageData
).
reply
(
httpStatusCodes
.
OK
,
{
events
:
[]
}
);
mock
.
onGet
(
endpoints
.
stageData
).
reply
(
httpStatusCodes
.
OK
,
stageData
,
headers
);
});
});
it
(
'
dispatches receiveStageDataSuccess with received data on success
'
,
()
=>
{
it
(
`commits
${
types
.
RECEIVE_STAGE_DATA_SUCCESS
}
with received data and headers on success`
,
()
=>
{
return
testAction
(
return
testAction
(
actions
.
fetchStageData
,
actions
.
fetchStageData
,
selectedStageSlug
,
selectedStageSlug
,
state
,
state
,
[],
[
[
{
type
:
'
requestStageData
'
},
{
{
type
:
'
receiveStageDataSuccess
'
,
type
:
types
.
RECEIVE_STAGE_DATA_SUCCESS
,
payload
:
{
events
:
[]
},
payload
:
stageData
,
},
{
type
:
types
.
SET_PAGINATION
,
payload
:
{
page
:
headers
[
'
X-Page
'
],
hasNextPage
:
true
},
},
},
],
],
[{
type
:
'
requestStageData
'
}],
);
);
});
});
describe
(
'
without a next page
'
,
()
=>
{
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
mock
.
onGet
(
endpoints
.
stageData
)
.
reply
(
httpStatusCodes
.
OK
,
{
events
:
[]
},
{
...
headers
,
'
X-Next-Page
'
:
null
});
});
it
(
'
sets hasNextPage to false
'
,
()
=>
{
return
testAction
(
actions
.
fetchStageData
,
selectedStageSlug
,
state
,
[
{
type
:
types
.
RECEIVE_STAGE_DATA_SUCCESS
,
payload
:
{
events
:
[]
},
},
{
type
:
types
.
SET_PAGINATION
,
payload
:
{
page
:
headers
[
'
X-Page
'
],
hasNextPage
:
false
},
},
],
[{
type
:
'
requestStageData
'
}],
);
});
});
describe
(
'
with a failing request
'
,
()
=>
{
describe
(
'
with a failing request
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
mock
=
new
MockAdapter
(
axios
);
...
@@ -190,18 +237,6 @@ describe('Value Stream Analytics actions', () => {
...
@@ -190,18 +237,6 @@ describe('Value Stream Analytics actions', () => {
);
);
});
});
});
});
describe
(
'
receiveStageDataSuccess
'
,
()
=>
{
it
(
`commits the
${
types
.
RECEIVE_STAGE_DATA_SUCCESS
}
mutation`
,
()
=>
{
return
testAction
(
actions
.
receiveStageDataSuccess
,
{
...
stageData
},
state
,
[{
type
:
types
.
RECEIVE_STAGE_DATA_SUCCESS
,
payload
:
{
events
:
[]
}
}],
[],
);
});
});
});
});
describe
(
'
receiveStageDataError
'
,
()
=>
{
describe
(
'
receiveStageDataError
'
,
()
=>
{
...
...
ee/spec/frontend/analytics/cycle_analytics/store/getters_spec.js
View file @
41ee917d
...
@@ -16,6 +16,8 @@ import {
...
@@ -16,6 +16,8 @@ import {
transformedStagePathData
,
transformedStagePathData
,
issueStage
,
issueStage
,
stageMedians
,
stageMedians
,
basePaginationResult
,
initialPaginationState
,
}
from
'
../mock_data
'
;
}
from
'
../mock_data
'
;
let
state
=
null
;
let
state
=
null
;
...
@@ -218,4 +220,24 @@ describe('Value Stream Analytics getters', () => {
...
@@ -218,4 +220,24 @@ describe('Value Stream Analytics getters', () => {
expect
(
getters
.
pathNavigationData
(
state
)).
toEqual
(
transformedStagePathData
);
expect
(
getters
.
pathNavigationData
(
state
)).
toEqual
(
transformedStagePathData
);
});
});
});
});
describe
(
'
paginationParams
'
,
()
=>
{
beforeEach
(()
=>
{
state
=
{
pagination
:
initialPaginationState
};
});
it
(
'
returns the `pagination` type
'
,
()
=>
{
expect
(
getters
.
paginationParams
(
state
)).
toEqual
(
basePaginationResult
);
});
it
(
'
returns the `sort` type
'
,
()
=>
{
expect
(
getters
.
paginationParams
(
state
)).
toEqual
(
basePaginationResult
);
});
it
(
'
with page=10, sets the `page` property
'
,
()
=>
{
const
page
=
10
;
state
=
{
pagination
:
{
...
initialPaginationState
,
page
}
};
expect
(
getters
.
paginationParams
(
state
)).
toEqual
({
...
basePaginationResult
,
page
});
});
});
});
});
ee/spec/frontend/analytics/cycle_analytics/store/mutations_spec.js
View file @
41ee917d
...
@@ -78,6 +78,8 @@ describe('Value Stream Analytics mutations', () => {
...
@@ -78,6 +78,8 @@ describe('Value Stream Analytics mutations', () => {
stages
:
[{},
{
name
:
"
Can't be blank
"
},
{},
{},
{},
{},
{},
{}],
stages
:
[{},
{
name
:
"
Can't be blank
"
},
{},
{},
{},
{},
{},
{}],
};
};
const
pagination
=
{
page
:
10
,
hasNextPage
:
true
};
it
.
each
`
it
.
each
`
mutation | payload | expectedState
mutation | payload | expectedState
${
types
.
SET_FEATURE_FLAGS
}
|
${{
hasDurationChart
:
true
}
} |
${{
featureFlags
:
{
hasDurationChart
:
true
}
}}
${
types
.
SET_FEATURE_FLAGS
}
|
${{
hasDurationChart
:
true
}
} |
${{
featureFlags
:
{
hasDurationChart
:
true
}
}}
...
@@ -91,6 +93,7 @@ describe('Value Stream Analytics mutations', () => {
...
@@ -91,6 +93,7 @@ describe('Value Stream Analytics mutations', () => {
${
types
.
SET_SELECTED_VALUE_STREAM
}
|
${
valueStreams
[
1
].
id
}
|
${{
selectedValueStream
:
{}
}}
${
types
.
SET_SELECTED_VALUE_STREAM
}
|
${
valueStreams
[
1
].
id
}
|
${{
selectedValueStream
:
{}
}}
$
{
types
.
RECEIVE_CREATE_VALUE_STREAM_SUCCESS
}
|
${
valueStreams
[
1
]}
|
${{
selectedValueStream
:
valueStreams
[
1
]
}
}
$
{
types
.
RECEIVE_CREATE_VALUE_STREAM_SUCCESS
}
|
${
valueStreams
[
1
]}
|
${{
selectedValueStream
:
valueStreams
[
1
]
}
}
${
types
.
RECEIVE_UPDATE_VALUE_STREAM_SUCCESS
}
|
${
valueStreams
[
1
]}
|
${{
selectedValueStream
:
valueStreams
[
1
]
}
}
${
types
.
RECEIVE_UPDATE_VALUE_STREAM_SUCCESS
}
|
${
valueStreams
[
1
]}
|
${{
selectedValueStream
:
valueStreams
[
1
]
}
}
${
types
.
SET_PAGINATION
}
|
${
pagination
}
|
${{
pagination
}
}
`
(
`
(
'
$mutation with payload $payload will update state with $expectedState
'
,
'
$mutation with payload $payload will update state with $expectedState
'
,
({
mutation
,
payload
,
expectedState
})
=>
{
({
mutation
,
payload
,
expectedState
})
=>
{
...
...
ee/spec/lib/gitlab/analytics/cycle_analytics/request_params_spec.rb
View file @
41ee917d
...
@@ -225,7 +225,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RequestParams do
...
@@ -225,7 +225,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RequestParams do
expect
(
data_collector_params
[
:direction
]).
to
eq
(
:asc
)
expect
(
data_collector_params
[
:direction
]).
to
eq
(
:asc
)
end
end
it
'adds
c
orting params to data attributes'
do
it
'adds
s
orting params to data attributes'
do
data_attributes
=
subject
.
to_data_attributes
data_attributes
=
subject
.
to_data_attributes
expect
(
data_attributes
[
:sort
]).
to
eq
(
'duration'
)
expect
(
data_attributes
[
:sort
]).
to
eq
(
'duration'
)
...
...
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