Commit 234ce02d authored by Martin Wortschack's avatar Martin Wortschack

Merge branch '301082-fe-vsa-add-sorting-to-stage-tables' into 'master'

[FE] VSA - Add sorting to stage tables

See merge request gitlab-org/gitlab!60793
parents 619ac0da b895d8f1
...@@ -124,15 +124,20 @@ export default { ...@@ -124,15 +124,20 @@ export default {
}, },
query() { query() {
const selectedProjectIds = this.selectedProjectIds?.length ? this.selectedProjectIds : null; const selectedProjectIds = this.selectedProjectIds?.length ? this.selectedProjectIds : null;
const stageParams = this.featureFlags.hasPathNavigation
? {
sort: (!this.isOverviewStageSelected && this.pagination?.sort) || null,
direction: (!this.isOverviewStageSelected && this.pagination?.direction) || null,
}
: {};
return { return {
value_stream_id: this.selectedValueStream?.id || null, value_stream_id: this.selectedValueStream?.id || null,
project_ids: selectedProjectIds, project_ids: selectedProjectIds,
created_after: toYmd(this.startDate), created_after: toYmd(this.startDate),
created_before: toYmd(this.endDate), created_before: toYmd(this.endDate),
// the `overview` stage is always the default, so dont persist the id if its selected stage_id: (!this.isOverviewStageSelected && this.selectedStage?.id) || null, // the `overview` stage is always the default, so dont persist the id if its selected
stage_id: ...stageParams,
this.selectedStage?.id && !this.isOverviewStageSelected ? this.selectedStage.id : null,
}; };
}, },
stageCount() { stageCount() {
...@@ -192,7 +197,7 @@ export default { ...@@ -192,7 +197,7 @@ export default {
onStageReorder(data) { onStageReorder(data) {
this.reorderStage(data); this.reorderStage(data);
}, },
onHandleSelectPage(data) { onHandleUpdatePagination(data) {
this.updateStageTablePagination(data); this.updateStageTablePagination(data);
}, },
}, },
...@@ -287,7 +292,7 @@ export default { ...@@ -287,7 +292,7 @@ export default {
:empty-state-message="selectedStageError" :empty-state-message="selectedStageError"
:no-data-svg-path="noDataSvgPath" :no-data-svg-path="noDataSvgPath"
:pagination="pagination" :pagination="pagination"
@handleSelectPage="onHandleSelectPage" @handleUpdatePagination="onHandleUpdatePagination"
/> />
</template> </template>
<stage-table <stage-table
......
<script> <script>
import { GlEmptyState, GlIcon, GlLink, GlLoadingIcon, GlPagination, GlTable } from '@gitlab/ui'; import { GlEmptyState, GlIcon, GlLink, GlLoadingIcon, GlPagination, GlTable } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { NOT_ENOUGH_DATA_ERROR } from '../constants'; import {
NOT_ENOUGH_DATA_ERROR,
PAGINATION_SORT_FIELD_END_EVENT,
PAGINATION_SORT_FIELD_DURATION,
PAGINATION_SORT_DIRECTION_ASC,
PAGINATION_SORT_DIRECTION_DESC,
} from '../constants';
import TotalTime from './total_time_component.vue'; import TotalTime from './total_time_component.vue';
const DEFAULT_WORKFLOW_TITLE_PROPERTIES = { thClass: 'gl-w-half', key: 'workflowTitleKey' }; const DEFAULT_WORKFLOW_TITLE_PROPERTIES = {
thClass: 'gl-w-half',
key: PAGINATION_SORT_FIELD_END_EVENT,
sortable: true,
};
const WORKFLOW_COLUMN_TITLES = { const WORKFLOW_COLUMN_TITLES = {
issues: { ...DEFAULT_WORKFLOW_TITLE_PROPERTIES, label: __('Issues') }, issues: { ...DEFAULT_WORKFLOW_TITLE_PROPERTIES, label: __('Issues') },
jobs: { ...DEFAULT_WORKFLOW_TITLE_PROPERTIES, label: __('Jobs') }, jobs: { ...DEFAULT_WORKFLOW_TITLE_PROPERTIES, label: __('Jobs') },
...@@ -50,6 +60,15 @@ export default { ...@@ -50,6 +60,15 @@ export default {
required: true, required: true,
}, },
}, },
data() {
const {
pagination: { sort, direction },
} = this;
return {
sort,
sortDesc: direction === PAGINATION_SORT_DIRECTION_DESC,
};
},
computed: { computed: {
isEmptyStage() { isEmptyStage() {
return !this.stageEvents.length; return !this.stageEvents.length;
...@@ -81,7 +100,15 @@ export default { ...@@ -81,7 +100,15 @@ export default {
return WORKFLOW_COLUMN_TITLES.issues; return WORKFLOW_COLUMN_TITLES.issues;
}, },
fields() { fields() {
return [this.workflowTitle, { key: 'time', label: __('Time'), thClass: 'gl-w-half' }]; return [
this.workflowTitle,
{
key: PAGINATION_SORT_FIELD_DURATION,
label: __('Time'),
thClass: 'gl-w-half',
sortable: true,
},
];
}, },
prevPage() { prevPage() {
return Math.max(this.pagination.page - 1, 0); return Math.max(this.pagination.page - 1, 0);
...@@ -98,7 +125,16 @@ export default { ...@@ -98,7 +125,16 @@ export default {
return item.title || item.name; return item.title || item.name;
}, },
onSelectPage(page) { onSelectPage(page) {
this.$emit('handleSelectPage', { page }); const { sort, direction } = this.pagination;
this.$emit('handleUpdatePagination', { sort, direction, page });
},
onSort({ sortBy, sortDesc }) {
this.sort = sortBy;
this.sortDesc = sortDesc;
this.$emit('handleUpdatePagination', {
sort: sortBy,
direction: sortDesc ? PAGINATION_SORT_DIRECTION_DESC : PAGINATION_SORT_DIRECTION_ASC,
});
}, },
}, },
}; };
...@@ -113,11 +149,15 @@ export default { ...@@ -113,11 +149,15 @@ export default {
stacked="lg" stacked="lg"
thead-class="border-bottom" thead-class="border-bottom"
show-empty show-empty
:sort-by.sync="sort"
:sort-direction.sync="pagination.direction"
:sort-desc.sync="sortDesc"
:fields="fields" :fields="fields"
:items="stageEvents" :items="stageEvents"
:empty-text="emptyStateMessage" :empty-text="emptyStateMessage"
@sort-changed="onSort"
> >
<template #cell(workflowTitleKey)="{ item }"> <template #cell(end_event)="{ item }">
<div data-testid="vsa-stage-event"> <div data-testid="vsa-stage-event">
<div v-if="item.id" data-testid="vsa-stage-content"> <div v-if="item.id" data-testid="vsa-stage-content">
<p class="gl-m-0"> <p class="gl-m-0">
...@@ -204,7 +244,7 @@ export default { ...@@ -204,7 +244,7 @@ export default {
</div> </div>
</div> </div>
</template> </template>
<template #cell(time)="{ item }"> <template #cell(duration)="{ item }">
<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>
......
...@@ -75,4 +75,7 @@ export const NOT_ENOUGH_DATA_ERROR = s__( ...@@ -75,4 +75,7 @@ export const NOT_ENOUGH_DATA_ERROR = s__(
); );
export const PAGINATION_TYPE = 'keyset'; export const PAGINATION_TYPE = 'keyset';
export const PAGINATION_SORT_FIELD = 'created_at'; export const PAGINATION_SORT_FIELD_END_EVENT = 'end_event';
export const PAGINATION_SORT_FIELD_DURATION = 'duration';
export const PAGINATION_SORT_DIRECTION_DESC = 'desc';
export const PAGINATION_SORT_DIRECTION_ASC = 'asc';
...@@ -29,6 +29,8 @@ export default () => { ...@@ -29,6 +29,8 @@ export default () => {
milestone_title = null, milestone_title = null,
assignee_username = [], assignee_username = [],
label_name = [], label_name = [],
sort,
direction,
} = urlQueryToFilter(window.location.search); } = urlQueryToFilter(window.location.search);
store.dispatch('initializeCycleAnalytics', { store.dispatch('initializeCycleAnalytics', {
...@@ -37,10 +39,8 @@ export default () => { ...@@ -37,10 +39,8 @@ export default () => {
selectedMilestone: milestone_title, selectedMilestone: milestone_title,
selectedAssigneeList: assignee_username, selectedAssigneeList: assignee_username,
selectedLabelList: label_name, selectedLabelList: label_name,
featureFlags: { featureFlags: { hasDurationChart, hasPathNavigation },
hasDurationChart, pagination: { sort: sort?.value || null, direction: direction?.value || null },
hasPathNavigation,
},
}); });
return new Vue({ return new Vue({
......
...@@ -31,9 +31,9 @@ export const setFeatureFlags = ({ commit }, featureFlags) => ...@@ -31,9 +31,9 @@ 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) => { export const setSelectedStage = ({ commit, getters: { paginationParams } }, stage) => {
commit(types.SET_SELECTED_STAGE, stage); commit(types.SET_SELECTED_STAGE, stage);
commit(types.SET_PAGINATION, { page: 1, hasNextPage: null }); commit(types.SET_PAGINATION, { ...paginationParams, page: 1, hasNextPage: null });
}; };
export const setDateRange = ({ commit, dispatch }, { skipFetch = false, startDate, endDate }) => { export const setDateRange = ({ commit, dispatch }, { skipFetch = false, startDate, endDate }) => {
...@@ -77,7 +77,7 @@ export const fetchStageData = ({ dispatch, getters, commit }, stageId) => { ...@@ -77,7 +77,7 @@ export const fetchStageData = ({ dispatch, getters, commit }, stageId) => {
.then(({ data, headers }) => { .then(({ data, headers }) => {
const { page = null, nextPage = null } = parseIntPagination(normalizeHeaders(headers)); const { page = null, nextPage = null } = parseIntPagination(normalizeHeaders(headers));
commit(types.RECEIVE_STAGE_DATA_SUCCESS, data); commit(types.RECEIVE_STAGE_DATA_SUCCESS, data);
commit(types.SET_PAGINATION, { page, hasNextPage: Boolean(nextPage) }); commit(types.SET_PAGINATION, { ...paginationParams, page, hasNextPage: Boolean(nextPage) });
}) })
.catch((error) => dispatch('receiveStageDataError', error)); .catch((error) => dispatch('receiveStageDataError', error));
}; };
...@@ -483,8 +483,8 @@ export const setFilters = ({ dispatch }) => { ...@@ -483,8 +483,8 @@ export const setFilters = ({ dispatch }) => {
export const updateStageTablePagination = ( export const updateStageTablePagination = (
{ commit, dispatch, state: { selectedStage } }, { commit, dispatch, state: { selectedStage } },
{ page }, paginationParams,
) => { ) => {
commit(types.SET_PAGINATION, { page }); commit(types.SET_PAGINATION, paginationParams);
return dispatch('fetchStageData', selectedStage.id); return dispatch('fetchStageData', selectedStage.id);
}; };
...@@ -4,12 +4,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils'; ...@@ -4,12 +4,7 @@ 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 { import { DEFAULT_VALUE_STREAM_ID, OVERVIEW_STAGE_CONFIG, PAGINATION_TYPE } from '../constants';
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;
...@@ -49,9 +44,10 @@ export const cycleAnalyticsRequestParams = (state, getters) => { ...@@ -49,9 +44,10 @@ export const cycleAnalyticsRequestParams = (state, getters) => {
}; };
}; };
export const paginationParams = ({ pagination: { page } }) => ({ export const paginationParams = ({ pagination: { page, sort, direction } }) => ({
pagination: PAGINATION_TYPE, pagination: PAGINATION_TYPE,
sort: PAGINATION_SORT_FIELD, sort,
direction,
page, page,
}); });
......
import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { PAGINATION_SORT_FIELD_END_EVENT, PAGINATION_SORT_DIRECTION_DESC } from '../constants';
import { transformRawStages, prepareStageErrors, formatMedianValuesWithOverview } from '../utils'; import { transformRawStages, prepareStageErrors, formatMedianValuesWithOverview } from '../utils';
import * as types from './mutation_types'; import * as types from './mutation_types';
...@@ -97,6 +99,7 @@ export default { ...@@ -97,6 +99,7 @@ export default {
selectedProjects = [], selectedProjects = [],
selectedValueStream = {}, selectedValueStream = {},
defaultStageConfig = [], defaultStageConfig = [],
pagination = {},
} = {}, } = {},
) { ) {
state.isLoading = true; state.isLoading = true;
...@@ -106,6 +109,12 @@ export default { ...@@ -106,6 +109,12 @@ export default {
state.startDate = startDate; state.startDate = startDate;
state.endDate = endDate; state.endDate = endDate;
state.defaultStageConfig = defaultStageConfig; state.defaultStageConfig = defaultStageConfig;
Vue.set(state, 'pagination', {
page: pagination.page ?? state.pagination.page,
sort: pagination.sort ?? state.pagination.sort,
direction: pagination.direction ?? state.pagination.direction,
});
}, },
[types.INITIALIZE_VALUE_STREAM_SUCCESS](state) { [types.INITIALIZE_VALUE_STREAM_SUCCESS](state) {
state.isLoading = false; state.isLoading = false;
...@@ -183,7 +192,12 @@ export default { ...@@ -183,7 +192,12 @@ export default {
return aName.toUpperCase() > bName.toUpperCase() ? 1 : -1; return aName.toUpperCase() > bName.toUpperCase() ? 1 : -1;
}); });
}, },
[types.SET_PAGINATION](state, { page, hasNextPage }) { [types.SET_PAGINATION](state, { page, hasNextPage, sort, direction }) {
state.pagination = { page, hasNextPage }; Vue.set(state, 'pagination', {
page,
hasNextPage,
sort: sort || PAGINATION_SORT_FIELD_END_EVENT,
direction: direction || PAGINATION_SORT_DIRECTION_DESC,
});
}, },
}; };
import { PAGINATION_SORT_FIELD_END_EVENT, PAGINATION_SORT_DIRECTION_DESC } from '../constants';
export default () => ({ export default () => ({
featureFlags: {}, featureFlags: {},
defaultStageConfig: [], defaultStageConfig: [],
...@@ -38,5 +40,7 @@ export default () => ({ ...@@ -38,5 +40,7 @@ export default () => ({
pagination: { pagination: {
page: null, page: null,
hasNextPage: false, hasNextPage: false,
sort: PAGINATION_SORT_FIELD_END_EVENT,
direction: PAGINATION_SORT_DIRECTION_DESC,
}, },
}); });
---
title: Add sorting to the VSA stage table
merge_request: 60793
author:
type: added
...@@ -16,6 +16,10 @@ import StageTableNav from 'ee/analytics/cycle_analytics/components/stage_table_n ...@@ -16,6 +16,10 @@ import StageTableNav from 'ee/analytics/cycle_analytics/components/stage_table_n
import StageTableNew from 'ee/analytics/cycle_analytics/components/stage_table_new.vue'; import StageTableNew from 'ee/analytics/cycle_analytics/components/stage_table_new.vue';
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 {
PAGINATION_SORT_FIELD_END_EVENT,
PAGINATION_SORT_DIRECTION_DESC,
} from 'ee/analytics/cycle_analytics/constants';
import createStore from 'ee/analytics/cycle_analytics/store'; import createStore from 'ee/analytics/cycle_analytics/store';
import Daterange from 'ee/analytics/shared/components/daterange.vue'; import Daterange from 'ee/analytics/shared/components/daterange.vue';
import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue'; import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
...@@ -611,11 +615,12 @@ describe('Value Stream Analytics component', () => { ...@@ -611,11 +615,12 @@ describe('Value Stream Analytics component', () => {
value_stream_id: selectedValueStream.id, value_stream_id: selectedValueStream.id,
created_after: toYmd(mockData.startDate), created_after: toYmd(mockData.startDate),
created_before: toYmd(mockData.endDate), created_before: toYmd(mockData.endDate),
stage_id: 1,
project_ids: null, project_ids: null,
stage_id: null,
}; };
const selectedProjectIds = mockData.selectedProjects.map(({ id }) => getIdFromGraphQLId(id)); const selectedProjectIds = mockData.selectedProjects.map(({ id }) => getIdFromGraphQLId(id));
const selectedStage = { title: 'Plan', id: 2 };
beforeEach(async () => { beforeEach(async () => {
commonUtils.historyPushState = jest.fn(); commonUtils.historyPushState = jest.fn();
...@@ -682,11 +687,6 @@ describe('Value Stream Analytics component', () => { ...@@ -682,11 +687,6 @@ describe('Value Stream Analytics component', () => {
}); });
describe('with selectedStage set', () => { describe('with selectedStage set', () => {
const selectedStage = {
title: 'Plan',
id: 2,
};
beforeEach(async () => { beforeEach(async () => {
wrapper = await createComponent(); wrapper = await createComponent();
store.dispatch('setSelectedStage', selectedStage); store.dispatch('setSelectedStage', selectedStage);
...@@ -703,5 +703,46 @@ describe('Value Stream Analytics component', () => { ...@@ -703,5 +703,46 @@ describe('Value Stream Analytics component', () => {
}); });
}); });
}); });
describe('with hasPathNavigation=true', () => {
it('does not set the sort and direction parameters', async () => {
wrapper = await createComponent({
featureFlags: {
hasPathNavigation: true,
},
});
await store.dispatch('initializeCycleAnalytics', initialCycleAnalyticsState);
await wrapper.vm.$nextTick();
await shouldMergeUrlParams(wrapper, {
...defaultParams,
created_after: toYmd(mockData.startDate),
created_before: toYmd(mockData.endDate),
project_ids: null,
});
});
describe('with a stage selected', () => {
beforeEach(async () => {
wrapper = await createComponent({
featureFlags: {
hasPathNavigation: true,
},
});
await store.dispatch('setSelectedStage', selectedStage);
await wrapper.vm.$nextTick();
});
it('sets the stage, sort and direction parameters', async () => {
await shouldMergeUrlParams(wrapper, {
...defaultParams,
stage_id: selectedStage.id,
direction: PAGINATION_SORT_DIRECTION_DESC,
sort: PAGINATION_SORT_FIELD_END_EVENT,
});
});
});
});
}); });
}); });
import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui'; import { GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils'; import { shallowMount, mount } from '@vue/test-utils';
import StageTableNew from 'ee/analytics/cycle_analytics/components/stage_table_new.vue'; import StageTableNew from 'ee/analytics/cycle_analytics/components/stage_table_new.vue';
import { PAGINATION_SORT_FIELD_DURATION } from 'ee/analytics/cycle_analytics/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { import {
stagingEvents, stagingEvents,
...@@ -26,6 +27,7 @@ const pagination = { page: 1, hasNextPage: true }; ...@@ -26,6 +27,7 @@ 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 findPagination = () => wrapper.findByTestId('vsa-stage-pagination');
const findTable = () => wrapper.findComponent(GlTable);
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) {
...@@ -289,7 +291,7 @@ describe('StageTable', () => { ...@@ -289,7 +291,7 @@ describe('StageTable', () => {
findPagination().vm.$emit('input', 2); findPagination().vm.$emit('input', 2);
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect(wrapper.emitted('handleSelectPage')[0]).toEqual([{ page: 2 }]); expect(wrapper.emitted('handleUpdatePagination')[0]).toEqual([{ page: 2 }]);
}); });
describe('with `hasNextPage=false', () => { describe('with `hasNextPage=false', () => {
...@@ -302,4 +304,38 @@ describe('StageTable', () => { ...@@ -302,4 +304,38 @@ describe('StageTable', () => {
}); });
}); });
}); });
describe('Sorting', () => {
beforeEach(() => {
wrapper = createComponent();
});
it('clicking a table column will update the sort field', () => {
findTable().vm.$emit('sort-changed', {
sortBy: PAGINATION_SORT_FIELD_DURATION,
sortDesc: true,
});
expect(wrapper.emitted('handleUpdatePagination')[0]).toEqual([
{
direction: 'desc',
sort: 'duration',
},
]);
});
it('with sortDesc=false will toggle the direction field', async () => {
findTable().vm.$emit('sort-changed', {
sortBy: PAGINATION_SORT_FIELD_DURATION,
sortDesc: false,
});
expect(wrapper.emitted('handleUpdatePagination')[0]).toEqual([
{
direction: 'asc',
sort: 'duration',
},
]);
});
});
}); });
...@@ -4,7 +4,8 @@ import { ...@@ -4,7 +4,8 @@ import {
TASKS_BY_TYPE_SUBJECT_ISSUE, TASKS_BY_TYPE_SUBJECT_ISSUE,
OVERVIEW_STAGE_CONFIG, OVERVIEW_STAGE_CONFIG,
PAGINATION_TYPE, PAGINATION_TYPE,
PAGINATION_SORT_FIELD, PAGINATION_SORT_DIRECTION_DESC,
PAGINATION_SORT_FIELD_END_EVENT,
} 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';
...@@ -305,9 +306,16 @@ export const selectedProjects = [ ...@@ -305,9 +306,16 @@ export const selectedProjects = [
export const pathNavIssueMetric = 172800; export const pathNavIssueMetric = 172800;
export const initialPaginationState = { page: null, hasNextPage: false }; export const initialPaginationState = {
page: null,
hasNextPage: false,
sort: PAGINATION_SORT_FIELD_END_EVENT,
direction: PAGINATION_SORT_DIRECTION_DESC,
};
export const basePaginationResult = { export const basePaginationResult = {
pagination: PAGINATION_TYPE, pagination: PAGINATION_TYPE,
sort: PAGINATION_SORT_FIELD, sort: PAGINATION_SORT_FIELD_END_EVENT,
direction: PAGINATION_SORT_DIRECTION_DESC,
page: null, page: null,
}; };
import {
PAGINATION_SORT_DIRECTION_DESC,
PAGINATION_SORT_FIELD_END_EVENT,
} 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';
...@@ -78,22 +82,23 @@ describe('Value Stream Analytics mutations', () => { ...@@ -78,22 +82,23 @@ describe('Value Stream Analytics mutations', () => {
stages: [{}, { name: "Can't be blank" }, {}, {}, {}, {}, {}, {}], stages: [{}, { name: "Can't be blank" }, {}, {}, {}, {}, {}, {}],
}; };
const pagination = { page: 10, hasNextPage: true }; const pagination = { page: 10, hasNextPage: true, sort: null, direction: null };
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 } }}
${types.SET_SELECTED_PROJECTS} | ${selectedProjects} | ${{ selectedProjects }} ${types.SET_SELECTED_PROJECTS} | ${selectedProjects} | ${{ selectedProjects }}
${types.SET_DATE_RANGE} | ${{ startDate, endDate }} | ${{ startDate, endDate }} ${types.SET_DATE_RANGE} | ${{ startDate, endDate }} | ${{ startDate, endDate }}
${types.SET_SELECTED_STAGE} | ${{ id: 'first-stage' }} | ${{ selectedStage: { id: 'first-stage' } }} ${types.SET_SELECTED_STAGE} | ${{ id: 'first-stage' }} | ${{ selectedStage: { id: 'first-stage' } }}
${types.RECEIVE_CREATE_VALUE_STREAM_ERROR} | ${valueStreamErrors} | ${{ createValueStreamErrors: expectedValueStreamErrors, isCreatingValueStream: false }} ${types.RECEIVE_CREATE_VALUE_STREAM_ERROR} | ${valueStreamErrors} | ${{ createValueStreamErrors: expectedValueStreamErrors, isCreatingValueStream: false }}
${types.RECEIVE_UPDATE_VALUE_STREAM_ERROR} | ${valueStreamErrors} | ${{ createValueStreamErrors: expectedValueStreamErrors, isEditingValueStream: false }} ${types.RECEIVE_UPDATE_VALUE_STREAM_ERROR} | ${valueStreamErrors} | ${{ createValueStreamErrors: expectedValueStreamErrors, isEditingValueStream: false }}
${types.RECEIVE_DELETE_VALUE_STREAM_ERROR} | ${'Some error occurred'} | ${{ deleteValueStreamError: 'Some error occurred' }} ${types.RECEIVE_DELETE_VALUE_STREAM_ERROR} | ${'Some error occurred'} | ${{ deleteValueStreamError: 'Some error occurred' }}
${types.RECEIVE_VALUE_STREAMS_SUCCESS} | ${valueStreams} | ${{ valueStreams, isLoadingValueStreams: false }} ${types.RECEIVE_VALUE_STREAMS_SUCCESS} | ${valueStreams} | ${{ valueStreams, isLoadingValueStreams: false }}
${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 }} ${types.SET_PAGINATION} | ${pagination} | ${{ pagination: { ...pagination, sort: PAGINATION_SORT_FIELD_END_EVENT, direction: PAGINATION_SORT_DIRECTION_DESC } }}
${types.SET_PAGINATION} | ${{ ...pagination, sort: 'duration', direction: 'asc' }} | ${{ pagination: { ...pagination, sort: 'duration', direction: 'asc' } }}
`( `(
'$mutation with payload $payload will update state with $expectedState', '$mutation with payload $payload will update state with $expectedState',
({ mutation, payload, expectedState }) => { ({ mutation, payload, expectedState }) => {
...@@ -217,6 +222,11 @@ describe('Value Stream Analytics mutations', () => { ...@@ -217,6 +222,11 @@ describe('Value Stream Analytics mutations', () => {
selectedProjects, selectedProjects,
createdAfter: '2019-12-31', createdAfter: '2019-12-31',
createdBefore: '2020-01-01', createdBefore: '2020-01-01',
pagination: {
page: 1,
sort: PAGINATION_SORT_FIELD_END_EVENT,
direction: PAGINATION_SORT_DIRECTION_DESC,
},
}; };
it.each` it.each`
...@@ -229,7 +239,19 @@ describe('Value Stream Analytics mutations', () => { ...@@ -229,7 +239,19 @@ describe('Value Stream Analytics mutations', () => {
state = {}; state = {};
mutations[types.INITIALIZE_VSA](state, initialData); mutations[types.INITIALIZE_VSA](state, initialData);
expect(state[stateKey]).toEqual(expectedState); expect(state[stateKey]).toBe(expectedState);
});
it.each`
stateKey | expectedState
${'page'} | ${1}
${'sort'} | ${PAGINATION_SORT_FIELD_END_EVENT}
${'direction'} | ${PAGINATION_SORT_DIRECTION_DESC}
`('$stateKey will be set to $expectedState', ({ stateKey, expectedState }) => {
state = {};
mutations[types.INITIALIZE_VSA](state, initialData);
expect(state.pagination[stateKey]).toBe(expectedState);
}); });
}); });
}); });
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