Commit 68f8c586 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Fix missing custom flag from transformed stages

Added basic tests for transformRawStages, to
ensure all stage properties are retained.

Minor review feedback
parent cf091d83
...@@ -703,7 +703,9 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) => { ...@@ -703,7 +703,9 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) => {
* @param {Object} obj Object to transform * @param {Object} obj Object to transform
* @returns {Object} * @returns {Object}
*/ */
export const convertObjectKeysToSnakeCase = (obj = {}) => // Follow up to add additional options param:
// https://gitlab.com/gitlab-org/gitlab/issues/39173
export const convertObjectPropsToSnakeCase = (obj = {}) =>
obj obj
? Object.entries(obj).reduce( ? Object.entries(obj).reduce(
(acc, [key, value]) => ({ ...acc, [convertToSnakeCase(key)]: value }), (acc, [key, value]) => ({ ...acc, [convertToSnakeCase(key)]: value }),
......
...@@ -59,7 +59,7 @@ export default { ...@@ -59,7 +59,7 @@ export default {
'isCreatingCustomStage', 'isCreatingCustomStage',
'isEditingCustomStage', 'isEditingCustomStage',
'selectedGroup', 'selectedGroup',
'selectedStageId', 'selectedStage',
'stages', 'stages',
'summary', 'summary',
'labels', 'labels',
...@@ -72,7 +72,7 @@ export default { ...@@ -72,7 +72,7 @@ export default {
]), ]),
...mapGetters(['hasNoAccessError', 'currentGroupPath', 'durationChartPlottableData']), ...mapGetters(['hasNoAccessError', 'currentGroupPath', 'durationChartPlottableData']),
shouldRenderEmptyState() { shouldRenderEmptyState() {
return !this.selectedGroup;g return !this.selectedGroup;
}, },
hasCustomizableCycleAnalytics() { hasCustomizableCycleAnalytics() {
return Boolean(this.glFeatures.customizableCycleAnalytics); return Boolean(this.glFeatures.customizableCycleAnalytics);
...@@ -108,7 +108,7 @@ export default { ...@@ -108,7 +108,7 @@ export default {
'fetchStageData', 'fetchStageData',
'setSelectedGroup', 'setSelectedGroup',
'setSelectedProjects', 'setSelectedProjects',
'setSelectedStageId', 'setSelectedStage',
'hideCustomStageForm', 'hideCustomStageForm',
'showCustomStageForm', 'showCustomStageForm',
'setDateRange', 'setDateRange',
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { isEqual } from 'underscore'; import { isEqual } from 'underscore';
import { GlButton, GlFormGroup, GlFormInput, GlFormSelect, GlLoadingIcon } from '@gitlab/ui'; import { GlButton, GlFormGroup, GlFormInput, GlFormSelect, GlLoadingIcon } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { convertObjectKeysToSnakeCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
import LabelsSelector from './labels_selector.vue'; import LabelsSelector from './labels_selector.vue';
import { STAGE_ACTIONS } from '../constants'; import { STAGE_ACTIONS } from '../constants';
import { import {
...@@ -152,7 +152,7 @@ export default { ...@@ -152,7 +152,7 @@ export default {
this.$emit('cancel'); this.$emit('cancel');
}, },
handleSave() { handleSave() {
const data = convertObjectKeysToSnakeCase(this.fields); const data = convertObjectPropsToSnakeCase(this.fields);
if (this.isEditingCustomStage) { if (this.isEditingCustomStage) {
const { id } = this.initialFields; const { id } = this.initialFields;
this.$emit(STAGE_ACTIONS.UPDATE, { ...data, id }); this.$emit(STAGE_ACTIONS.UPDATE, { ...data, id });
......
...@@ -121,20 +121,6 @@ export default { ...@@ -121,20 +121,6 @@ export default {
return this.isEditingCustomStage ? this.currentStage : {}; return this.isEditingCustomStage ? this.currentStage : {};
}, },
}, },
methods: {
selectStage(stage) {
this.$emit(STAGE_ACTIONS.SELECT, stage);
},
editStage(stage) {
this.$emit(STAGE_ACTIONS.EDIT, stage);
},
hideStage(stageId) {
this.$emit(STAGE_ACTIONS.HIDE, { id: stageId, hidden: true });
},
removeStage(stageId) {
this.$emit(STAGE_ACTIONS.REMOVE, stageId);
},
},
STAGE_ACTIONS, STAGE_ACTIONS,
}; };
</script> </script>
...@@ -166,10 +152,10 @@ export default { ...@@ -166,10 +152,10 @@ export default {
:is-active="!isCreatingCustomStage && stage.id === currentStage.id" :is-active="!isCreatingCustomStage && stage.id === currentStage.id"
:can-edit="canEditStages" :can-edit="canEditStages"
:is-default-stage="!stage.custom" :is-default-stage="!stage.custom"
@remove="removeStage(stage.id)" @remove="$emit($options.STAGE_ACTIONS.REMOVE, stage.id)"
@hide="hideStage(stage.id)" @hide="$emit($options.STAGE_ACTIONS.HIDE, { id: stage.id, hidden: true })"
@select="selectStage(stage)" @select="$emit($options.STAGE_ACTIONS.SELECT, stage)"
@edit="editStage(stage)" @edit="$emit($options.STAGE_ACTIONS.EDIT, stage)"
/> />
<add-stage-button <add-stage-button
v-if="canEditStages" v-if="canEditStages"
......
...@@ -53,6 +53,8 @@ export const transformRawStages = (stages = []) => ...@@ -53,6 +53,8 @@ export const transformRawStages = (stages = []) =>
id, id,
title, title,
slug: custom ? id : convertToSnakeCase(title), slug: custom ? id : convertToSnakeCase(title),
custom,
name: title, // editing a stage takes 'name' as a parameter, but the api returns title
})) }))
.sort((a, b) => a.id > b.id); .sort((a, b) => a.id > b.id);
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Cycle analytics utils transformRawStages retains all the stage properties 1`] = `
Array [
Object {
"custom": false,
"description": "Time before an issue gets scheduled",
"hidden": false,
"id": "issue",
"legend": "",
"name": "Issue",
"slug": "issue",
"title": "Issue",
},
Object {
"custom": true,
"description": "",
"endEventIdentifier": "issue_first_added_to_board",
"hidden": false,
"id": 18,
"legend": "",
"name": "Coolest beans stage",
"slug": 18,
"startEventIdentifier": "issue_first_mentioned_in_commit",
"title": "Coolest beans stage",
},
]
`;
...@@ -75,6 +75,16 @@ export const codeEvents = stageFixtures.code; ...@@ -75,6 +75,16 @@ export const codeEvents = stageFixtures.code;
export const testEvents = stageFixtures.test; export const testEvents = stageFixtures.test;
export const stagingEvents = stageFixtures.staging; export const stagingEvents = stageFixtures.staging;
export const productionEvents = stageFixtures.production; export const productionEvents = stageFixtures.production;
export const rawCustomStage = {
title: 'Coolest beans stage',
hidden: false,
legend: '',
description: '',
id: 18,
custom: true,
start_event_identifier: 'issue_first_mentioned_in_commit',
end_event_identifier: 'issue_first_added_to_board',
};
const { events: rawCustomStageEvents } = customizableStagesAndEvents; const { events: rawCustomStageEvents } = customizableStagesAndEvents;
const camelCasedStageEvents = rawCustomStageEvents.map(deepCamelCase); const camelCasedStageEvents = rawCustomStageEvents.map(deepCamelCase);
......
...@@ -8,6 +8,7 @@ import { ...@@ -8,6 +8,7 @@ import {
nestQueryStringKeys, nestQueryStringKeys,
flattenDurationChartData, flattenDurationChartData,
getDurationChartData, getDurationChartData,
transformRawStages,
} from 'ee/analytics/cycle_analytics/utils'; } from 'ee/analytics/cycle_analytics/utils';
import { import {
customStageEvents as events, customStageEvents as events,
...@@ -19,6 +20,8 @@ import { ...@@ -19,6 +20,8 @@ import {
durationChartPlottableData, durationChartPlottableData,
startDate, startDate,
endDate, endDate,
issueStage,
rawCustomStage,
} from './mock_data'; } from './mock_data';
const labelEvents = [labelStartEvent, labelStopEvent].map(i => i.identifier); const labelEvents = [labelStartEvent, labelStopEvent].map(i => i.identifier);
...@@ -153,4 +156,26 @@ describe('Cycle analytics utils', () => { ...@@ -153,4 +156,26 @@ describe('Cycle analytics utils', () => {
expect(plottableData).toStrictEqual(durationChartPlottableData); expect(plottableData).toStrictEqual(durationChartPlottableData);
}); });
}); });
describe('transformRawStages', () => {
it('retains all the stage properties', () => {
const transformed = transformRawStages([issueStage, rawCustomStage]);
expect(transformed).toMatchSnapshot();
});
it('converts object properties from snake_case to camelCase', () => {
const [transformedCustomStage] = transformRawStages([rawCustomStage]);
expect(transformedCustomStage).toMatchObject({
endEventIdentifier: 'issue_first_added_to_board',
startEventIdentifier: 'issue_first_mentioned_in_commit',
});
});
it('sets the slug to the value of the stage id', () => {
const transformed = transformRawStages([issueStage, rawCustomStage]);
transformed.forEach(t => {
expect(t.slug).toEqual(t.id);
});
});
});
}); });
...@@ -721,7 +721,7 @@ describe('common_utils', () => { ...@@ -721,7 +721,7 @@ describe('common_utils', () => {
}); });
}); });
describe('convertObjectKeysToSnakeCase', () => { describe('convertObjectPropsToSnakeCase', () => {
it('converts each object key to snake case', () => { it('converts each object key to snake case', () => {
const obj = { const obj = {
some: 'some', some: 'some',
...@@ -729,7 +729,7 @@ describe('common_utils', () => { ...@@ -729,7 +729,7 @@ describe('common_utils', () => {
likeThisLongOne: 'likeThisLongOne', likeThisLongOne: 'likeThisLongOne',
}; };
expect(commonUtils.convertObjectKeysToSnakeCase(obj)).toEqual({ expect(commonUtils.convertObjectPropsToSnakeCase(obj)).toEqual({
some: 'some', some: 'some',
cool_object: 'cool object', cool_object: 'cool object',
like_this_long_one: 'likeThisLongOne', like_this_long_one: 'likeThisLongOne',
...@@ -738,7 +738,7 @@ describe('common_utils', () => { ...@@ -738,7 +738,7 @@ describe('common_utils', () => {
it('returns an empty object if there are no keys', () => { it('returns an empty object if there are no keys', () => {
['', {}, [], null].forEach(badObj => { ['', {}, [], null].forEach(badObj => {
expect(commonUtils.convertObjectKeysToSnakeCase(badObj)).toEqual({}); expect(commonUtils.convertObjectPropsToSnakeCase(badObj)).toEqual({});
}); });
}); });
}); });
......
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