Commit 9b7630ff authored by Eulyeon Ko's avatar Eulyeon Ko

Move getter methods into roadmap_item_utils.js

The following getters have been only used in the context
of initializing fetched raw data using the functions from
roadmap_item_utils.js:

getters.lastTimeframeIndex
getters.timeframeStartDate
getters.timeframeEndDate

Having these coupled to vuex makes it hard to generate-
mock data needed for testing, thus we are moving them
into roadmap_item_utils.js to use as pure helper functions.
parent 6e5132d3
......@@ -100,6 +100,11 @@ export function formatDateAsMonth(datetime, options = {}) {
return getMonthNames(abbreviated)[month];
}
/**
* Returns a date object corresponding to the given date string.
*/
export const dateFromString = dateString => new Date(dateFormat(dateString));
/**
* @example
* dateFormat('2017-12-05','mmm d, yyyy h:MMtt Z' ) -> "Dec 5, 2017 12:00am GMT+0000"
......
......@@ -78,15 +78,16 @@ export const fetchChildrenEpics = (state, { parentItem }) => {
};
export const receiveEpicsSuccess = (
{ commit, dispatch, state, getters },
{ commit, dispatch, state },
{ rawEpics, newEpic, timeframeExtended },
) => {
const epicIds = [];
const epics = rawEpics.reduce((filteredEpics, epic) => {
const { presetType, timeframe } = state;
const formattedEpic = roadmapItemUtils.formatRoadmapItemDetails(
epic,
getters.timeframeStartDate,
getters.timeframeEndDate,
roadmapItemUtils.timeframeStartDate(presetType, timeframe),
roadmapItemUtils.timeframeEndDate(presetType, timeframe),
);
formattedEpic.isChildEpic = false;
......@@ -126,14 +127,15 @@ export const requestChildrenEpics = ({ commit }, { parentItemId }) => {
commit(types.REQUEST_CHILDREN_EPICS, { parentItemId });
};
export const receiveChildrenSuccess = (
{ commit, dispatch, getters },
{ commit, dispatch, state },
{ parentItemId, rawChildren },
) => {
const children = rawChildren.reduce((filteredChildren, epic) => {
const { presetType, timeframe } = state;
const formattedChild = roadmapItemUtils.formatRoadmapItemDetails(
epic,
getters.timeframeStartDate,
getters.timeframeEndDate,
roadmapItemUtils.timeframeStartDate(presetType, timeframe),
roadmapItemUtils.timeframeEndDate(presetType, timeframe),
);
formattedChild.isChildEpic = true;
......@@ -180,13 +182,15 @@ export const fetchEpicsForTimeframe = ({ state, commit, dispatch }, { timeframe
*
* @param extendAs An EXTEND_AS enum value
*/
export const extendTimeframe = ({ commit, state, getters }, { extendAs }) => {
export const extendTimeframe = ({ commit, state }, { extendAs }) => {
const isExtendTypePrepend = extendAs === EXTEND_AS.PREPEND;
const { presetType, timeframe } = state;
const timeframeToExtend = extendTimeframeForPreset({
extendAs,
presetType: state.presetType,
initialDate: isExtendTypePrepend ? getters.timeframeStartDate : getters.timeframeEndDate,
presetType,
initialDate: isExtendTypePrepend
? roadmapItemUtils.timeframeStartDate(presetType, timeframe)
: roadmapItemUtils.timeframeEndDate(presetType, timeframe),
});
if (isExtendTypePrepend) {
......@@ -233,22 +237,22 @@ export const toggleEpic = ({ state, dispatch }, { parentItem }) => {
* For epics that have no start or end date, this function updates their start and end dates
* so that the epic bars get longer to appear infinitely scrolling.
*/
export const refreshEpicDates = ({ commit, state, getters }) => {
export const refreshEpicDates = ({ commit, state }) => {
const epics = state.epics.map((epic) => {
// Update child epic dates too
if (epic.children?.edges?.length > 0) {
epic.children.edges.map((childEpic) =>
roadmapItemUtils.processRoadmapItemDates(
childEpic,
getters.timeframeStartDate,
getters.timeframeEndDate,
roadmapItemUtils.timeframeStartDate(presetType, timeframe),
roadmapItemUtils.timeframeEndDate(presetType, timeframe),
),
);
}
return roadmapItemUtils.processRoadmapItemDates(
epic,
getters.timeframeStartDate,
getters.timeframeEndDate,
roadmapItemUtils.timeframeStartDate(presetType, timeframe),
roadmapItemUtils.timeframeEndDate(presetType, timeframe),
);
});
......@@ -298,15 +302,16 @@ export const fetchMilestones = ({ state, dispatch }) => {
};
export const receiveMilestonesSuccess = (
{ commit, state, getters },
{ commit, state },
{ rawMilestones, newMilestone }, // timeframeExtended
) => {
const { presetType, timeframe } = state;
const milestoneIds = [];
const milestones = rawMilestones.reduce((filteredMilestones, milestone) => {
const formattedMilestone = roadmapItemUtils.formatRoadmapItemDetails(
milestone,
getters.timeframeStartDate,
getters.timeframeEndDate,
roadmapItemUtils.timeframeStartDate(presetType, timeframe),
roadmapItemUtils.timeframeEndDate(presetType, timeframe),
);
// Exclude any Milestone that has invalid dates
// or is already present in Roadmap timeline
......@@ -332,12 +337,19 @@ export const receiveMilestonesFailure = ({ commit }) => {
flash(s__('GroupRoadmap|Something went wrong while fetching milestones'));
};
<<<<<<< HEAD
export const refreshMilestoneDates = ({ commit, state, getters }) => {
const milestones = state.milestones.map((milestone) =>
=======
export const refreshMilestoneDates = ({ commit, state }) => {
const { presetType, timeframe } = state;
const milestones = state.milestones.map(milestone =>
>>>>>>> 1290c5ff943 (Move getter methods into roadmap_item_utils.js)
roadmapItemUtils.processRoadmapItemDates(
milestone,
getters.timeframeStartDate,
getters.timeframeEndDate,
roadmapItemUtils.timeframeStartDate(presetType, timeframe),
roadmapItemUtils.timeframeEndDate(presetType, timeframe),
),
);
......
......@@ -2,7 +2,6 @@ import Vue from 'vue';
import Vuex from 'vuex';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
import state from './state';
......@@ -11,7 +10,6 @@ Vue.use(Vuex);
export default () =>
new Vuex.Store({
actions,
getters,
mutations,
state: state(),
});
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { newDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
import { PRESET_TYPES, DAYS_IN_WEEK } from '../constants';
/**
* Updates provided `epic` or `milestone` object with necessary props
* representing underlying dates.
......@@ -109,3 +111,40 @@ export const extractGroupMilestones = (edges) =>
edges.map(({ node, milestoneNode = node }) => ({
...milestoneNode,
}));
/**
* Returns number representing index of last item of timeframe array
*
* @param {Array} timeframe
*/
export const lastTimeframeIndex = timeframe => timeframe.length - 1;
/**
* Returns first item of the timeframe array
*
* @param {string} presetType
* @param {Array} timeframe
*/
export const timeframeStartDate = (presetType, timeframe) => {
if (presetType === PRESET_TYPES.QUARTERS) {
return timeframe[0].range[0];
}
return timeframe[0];
};
/**
* Returns last item of the timeframe array depending on preset type set.
*
* @param {string} presetType
* @param {Array} timeframe
*/
export const timeframeEndDate = (presetType, timeframe) => {
if (presetType === PRESET_TYPES.QUARTERS) {
return timeframe[lastTimeframeIndex(timeframe)].range[2];
} else if (presetType === PRESET_TYPES.MONTHS) {
return timeframe[lastTimeframeIndex(timeframe)];
}
const endDate = newDate(timeframe[lastTimeframeIndex(timeframe)]);
endDate.setDate(endDate.getDate() + DAYS_IN_WEEK);
return endDate;
};
import { PRESET_TYPES } from 'ee/roadmap/constants';
import * as getters from 'ee/roadmap/store/getters';
describe('Roadmap Store Getters', () => {
describe('lastTimeframeIndex', () => {
it('Should return last index of the timeframe array from state', () => {
const roadmapState = {
timeframe: [1, 2, 3, 4],
};
expect(getters.lastTimeframeIndex(roadmapState)).toBe(3);
});
});
describe('timeframeStartDate', () => {
it('Should return first item of the timeframe range array from the state when preset type is Quarters', () => {
const roadmapState = {
timeframe: [{ range: ['foo', 'bar', 'baz'] }, { range: ['abc', 'cde', 'efg'] }],
presetType: PRESET_TYPES.QUARTERS,
};
expect(getters.timeframeStartDate(roadmapState)).toBe('foo');
});
it('Should return first item of the timeframe array from the state when preset type is Months or Weeks', () => {
const roadmapState = {
timeframe: ['foo', 'bar', 'baz'],
presetType: PRESET_TYPES.MONTHS,
};
expect(getters.timeframeStartDate(roadmapState)).toBe('foo');
roadmapState.presetType = PRESET_TYPES.WEEKS;
expect(getters.timeframeStartDate(roadmapState)).toBe('foo');
});
});
describe('timeframeEndDate', () => {
it('Should return last item of the timeframe range array from the state when preset type is Quarters', () => {
const roadmapState = {
timeframe: [{ range: ['foo', 'bar', 'baz'] }, { range: ['abc', 'cde', 'efg'] }],
presetType: PRESET_TYPES.QUARTERS,
};
expect(
getters.timeframeEndDate(roadmapState, {
lastTimeframeIndex: roadmapState.timeframe.length - 1,
}),
).toBe('efg');
});
it('Should return last item of the timeframe array from the state when preset type is Months', () => {
const roadmapState = {
timeframe: ['foo', 'bar', 'baz'],
presetType: PRESET_TYPES.MONTHS,
};
expect(
getters.timeframeEndDate(roadmapState, {
lastTimeframeIndex: roadmapState.timeframe.length - 1,
}),
).toBe('baz');
});
it('Should return last item of the timeframe array from the state when preset type is Weeks', () => {
const roadmapState = {
timeframe: [new Date(2018, 11, 23), new Date(2018, 11, 30), new Date(2019, 0, 6)],
presetType: PRESET_TYPES.WEEKS,
};
expect(
getters
.timeframeEndDate(roadmapState, {
lastTimeframeIndex: roadmapState.timeframe.length - 1,
})
.getTime(),
).toBe(new Date(2019, 0, 13).getTime());
});
});
});
import * as roadmapItemUtils from 'ee/roadmap/utils/roadmap_item_utils';
import { parsePikadayDate } from '~/lib/utils/datetime_utility';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { dateFromString, parsePikadayDate } from '~/lib/utils/datetime_utility';
import { rawEpics, mockGroupMilestonesQueryResponse } from '../mock_data';
......@@ -127,3 +128,47 @@ describe('extractGroupMilestones', () => {
);
});
});
describe('lastTimeframeIndex', () => {
it('Should return last index of the timeframe array', () => {
const timeframe = [1, 2, 3, 4];
expect(roadmapItemUtils.lastTimeframeIndex(timeframe)).toBe(3);
});
});
describe.each`
presetType | timeframe
${PRESET_TYPES.QUARTERS} | ${[{ range: ['foo', 'bar', 'baz'] }, { range: ['abc', 'cde', 'efg'] }]}
${PRESET_TYPES.MONTHS} | ${['foo', 'bar', 'baz']}
${PRESET_TYPES.WEEKS} | ${['foo', 'bar', 'baz']}
`('timeframeStartDate', ({ presetType, timeframe }) => {
it(`Should return first item of the timeframe range array when preset type is ${presetType}`, () => {
expect(roadmapItemUtils.timeframeStartDate(presetType, timeframe)).toBe('foo');
});
});
describe('timeframeEndDate', () => {
it.each`
presetType | lastItem | timeframe
${PRESET_TYPES.QUARTERS} | ${'efg'} | ${[{ range: ['foo', 'bar', 'baz'] }, { range: ['abc', 'cde', 'efg'] }]}
${PRESET_TYPES.MONTHS} | ${'baz'} | ${['foo', 'bar', 'baz']}
`(
`Should return last item of the timeframe range array when preset type is $presetType`,
({ presetType, lastItem, timeframe }) => {
expect(roadmapItemUtils.timeframeEndDate(presetType, timeframe)).toBe(lastItem);
},
);
it('Should return last item of the timeframe array from the state when preset type is WEEKS', () => {
const timeframe = [
dateFromString('Dec 23 2018'),
dateFromString('Dec 30 2018'),
dateFromString('Jan 6 2019'),
];
expect(roadmapItemUtils.timeframeEndDate(PRESET_TYPES.WEEKS, timeframe).getTime()).toBe(
dateFromString('Jan 13 2019').getTime(),
);
});
});
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