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
817f6d4d
Commit
817f6d4d
authored
May 15, 2020
by
Ezekiel Kigbo
Committed by
Illya Klymov
May 15, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move custom stage specs to folder
Moves the specs specifically for custom stages into a separate dir
parent
f35bf8cb
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
590 additions
and
426 deletions
+590
-426
ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
...javascripts/analytics/cycle_analytics/components/base.vue
+4
-18
ee/app/assets/javascripts/analytics/cycle_analytics/components/custom_stage_form.vue
...nalytics/cycle_analytics/components/custom_stage_form.vue
+66
-76
ee/app/assets/javascripts/analytics/cycle_analytics/components/stage_table_nav.vue
.../analytics/cycle_analytics/components/stage_table_nav.vue
+1
-5
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/actions.js
...cs/cycle_analytics/store/modules/custom_stages/actions.js
+4
-1
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/mutation_types.js
...e_analytics/store/modules/custom_stages/mutation_types.js
+2
-1
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/mutations.js
.../cycle_analytics/store/modules/custom_stages/mutations.js
+6
-1
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/state.js
...tics/cycle_analytics/store/modules/custom_stages/state.js
+1
-0
ee/spec/frontend/analytics/cycle_analytics/components/custom_stage_form_spec.js
...tics/cycle_analytics/components/custom_stage_form_spec.js
+149
-94
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
+2
-2
ee/spec/frontend/analytics/cycle_analytics/store/actions_spec.js
.../frontend/analytics/cycle_analytics/store/actions_spec.js
+0
-164
ee/spec/frontend/analytics/cycle_analytics/store/modules/custom_stages/actions_spec.js
...cle_analytics/store/modules/custom_stages/actions_spec.js
+261
-0
ee/spec/frontend/analytics/cycle_analytics/store/modules/custom_stages/getters_spec.js
...cle_analytics/store/modules/custom_stages/getters_spec.js
+15
-0
ee/spec/frontend/analytics/cycle_analytics/store/modules/custom_stages/mutations_spec.js
...e_analytics/store/modules/custom_stages/mutations_spec.js
+78
-0
ee/spec/frontend/analytics/cycle_analytics/store/mutations_spec.js
...rontend/analytics/cycle_analytics/store/mutations_spec.js
+1
-64
No files found.
ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
View file @
817f6d4d
...
@@ -70,14 +70,9 @@ export default {
...
@@ -70,14 +70,9 @@ export default {
'
endDate
'
,
'
endDate
'
,
'
medians
'
,
'
medians
'
,
]),
]),
...
mapState
(
'
customStages
'
,
[
// NOTE: formEvents are fetched in the same request as the list of stages (fetchGroupStagesAndEvents)
'
isSavingCustomStage
'
,
// so i think its ok to bind formEvents here even though its only used as a prop to the custom-stage-form
'
isCreatingCustomStage
'
,
...
mapState
(
'
customStages
'
,
[
'
isCreatingCustomStage
'
,
'
formEvents
'
]),
'
isEditingCustomStage
'
,
'
formEvents
'
,
'
formErrors
'
,
'
formInitialData
'
,
]),
...
mapGetters
([
...
mapGetters
([
'
hasNoAccessError
'
,
'
hasNoAccessError
'
,
'
currentGroupPath
'
,
'
currentGroupPath
'
,
...
@@ -106,9 +101,6 @@ export default {
...
@@ -106,9 +101,6 @@ export default {
isLoadingTypeOfWork
()
{
isLoadingTypeOfWork
()
{
return
this
.
isLoadingTasksByTypeChartTopLabels
||
this
.
isLoadingTasksByTypeChart
;
return
this
.
isLoadingTasksByTypeChartTopLabels
||
this
.
isLoadingTasksByTypeChart
;
},
},
isUpdatingCustomStage
()
{
return
this
.
isEditingCustomStage
&&
this
.
isSavingCustomStage
;
},
hasDateRangeSet
()
{
hasDateRangeSet
()
{
return
this
.
startDate
&&
this
.
endDate
;
return
this
.
startDate
&&
this
.
endDate
;
},
},
...
@@ -169,6 +161,7 @@ export default {
...
@@ -169,6 +161,7 @@ export default {
this
.
showCreateForm
();
this
.
showCreateForm
();
},
},
onShowEditStageForm
(
initData
=
{})
{
onShowEditStageForm
(
initData
=
{})
{
this
.
setSelectedStage
(
initData
);
this
.
showEditForm
(
initData
);
this
.
showEditForm
(
initData
);
},
},
onCreateCustomStage
(
data
)
{
onCreateCustomStage
(
data
)
{
...
@@ -299,7 +292,6 @@ export default {
...
@@ -299,7 +292,6 @@ export default {
:stages=
"activeStages"
:stages=
"activeStages"
:medians=
"medians"
:medians=
"medians"
:is-creating-custom-stage=
"isCreatingCustomStage"
:is-creating-custom-stage=
"isCreatingCustomStage"
:custom-stage-form-active=
"customStageFormActive"
:can-edit-stages=
"true"
:can-edit-stages=
"true"
:custom-ordering=
"enableCustomOrdering"
:custom-ordering=
"enableCustomOrdering"
@
reorderStage=
"onStageReorder"
@
reorderStage=
"onStageReorder"
...
@@ -311,14 +303,8 @@ export default {
...
@@ -311,14 +303,8 @@ export default {
/>
/>
</
template
>
</
template
>
<
template
v-if=
"customStageFormActive"
#content
>
<
template
v-if=
"customStageFormActive"
#content
>
<gl-loading-icon
v-if=
"isUpdatingCustomStage"
class=
"mt-4"
size=
"md"
/>
<custom-stage-form
<custom-stage-form
v-else
:events=
"formEvents"
:events=
"formEvents"
:is-saving-custom-stage=
"isSavingCustomStage"
:initial-fields=
"formInitialData"
:is-editing-custom-stage=
"isEditingCustomStage"
:errors=
"formErrors"
@
createStage=
"onCreateCustomStage"
@
createStage=
"onCreateCustomStage"
@
updateStage=
"onUpdateCustomStage"
@
updateStage=
"onUpdateCustomStage"
@
clearErrors=
"$emit('clearFormErrors')"
@
clearErrors=
"$emit('clearFormErrors')"
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/components/custom_stage_form.vue
View file @
817f6d4d
<
script
>
<
script
>
import
{
mapGetters
}
from
'
vuex
'
;
import
{
mapGetters
,
mapState
}
from
'
vuex
'
;
import
{
isEqual
}
from
'
lodash
'
;
import
{
isEqual
}
from
'
lodash
'
;
import
{
import
{
GlFormGroup
,
GlFormGroup
,
...
@@ -33,23 +33,37 @@ const defaultFields = {
...
@@ -33,23 +33,37 @@ const defaultFields = {
endEventLabelId
:
null
,
endEventLabelId
:
null
,
};
};
export
const
initializeFormData
=
({
emptyFieldState
,
initialFields
,
errors
})
=>
{
const
defaultErrors
=
{
const
defaultErrors
=
initialFields
?.
endEventIdentifier
id
:
[],
?
{
...
emptyFieldState
,
endEventIdentifier
:
null
}
name
:
[],
startEventIdentifier
:
[],
startEventLabelId
:
[],
endEventIdentifier
:
[],
endEventLabelId
:
[],
};
const
ERRORS
=
{
START_EVENT_REQUIRED
:
s__
(
'
CustomCycleAnalytics|Please select a start event first
'
),
STAGE_NAME_EXISTS
:
s__
(
'
CustomCycleAnalytics|Stage name already exists
'
),
INVALID_EVENT_PAIRS
:
s__
(
'
CustomCycleAnalytics|Start event changed, please select a valid stop event
'
,
),
};
export
const
initializeFormData
=
({
emptyFieldState
=
defaultFields
,
fields
,
errors
})
=>
{
const
initErrors
=
fields
?.
endEventIdentifier
?
defaultErrors
:
{
:
{
...
emptyFieldState
,
...
defaultErrors
,
endEventIdentifier
:
endEventIdentifier
:
!
fields
?.
startEventIdentifier
?
[
ERRORS
.
START_EVENT_REQUIRED
]
:
[],
initialFields
&&
!
initialFields
.
startEventIdentifier
?
[
s__
(
'
CustomCycleAnalytics|Please select a start event first
'
)]
:
null
,
};
};
return
{
return
{
fields
:
{
fields
:
{
...
emptyFieldState
,
...
emptyFieldState
,
...
initialF
ields
,
...
f
ields
,
},
},
fieldE
rrors
:
{
e
rrors
:
{
...
defaul
tErrors
,
...
ini
tErrors
,
...
errors
,
...
errors
,
},
},
};
};
...
@@ -72,42 +86,23 @@ export default {
...
@@ -72,42 +86,23 @@ export default {
type
:
Array
,
type
:
Array
,
required
:
true
,
required
:
true
,
},
},
initialFields
:
{
type
:
Object
,
required
:
false
,
default
:
()
=>
{},
},
isSavingCustomStage
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isEditingCustomStage
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
errors
:
{
type
:
Object
,
required
:
false
,
default
:
null
,
},
},
},
data
()
{
data
()
{
const
{
initialFields
=
{},
errors
=
null
}
=
this
;
const
{
fields
,
fieldErrors
}
=
initializeFormData
({
emptyFieldState
:
defaultFields
,
initialFields
,
errors
,
});
return
{
return
{
labelEvents
:
getLabelEventsIdentifiers
(
this
.
events
),
labelEvents
:
getLabelEventsIdentifiers
(
this
.
events
),
fields
,
fields
:
{}
,
fieldErrors
,
errors
:
[]
,
};
};
},
},
computed
:
{
computed
:
{
...
mapGetters
([
'
hiddenStages
'
]),
...
mapGetters
([
'
hiddenStages
'
]),
...
mapState
(
'
customStages
'
,
[
'
isLoading
'
,
'
isSavingCustomStage
'
,
'
isEditingCustomStage
'
,
'
formInitialData
'
,
'
formErrors
'
,
]),
startEventOptions
()
{
startEventOptions
()
{
return
[
return
[
{
value
:
null
,
text
:
s__
(
'
CustomCycleAnalytics|Select start event
'
)
},
{
value
:
null
,
text
:
s__
(
'
CustomCycleAnalytics|Select start event
'
)
},
...
@@ -132,8 +127,7 @@ export default {
...
@@ -132,8 +127,7 @@ export default {
},
},
hasErrors
()
{
hasErrors
()
{
return
(
return
(
this
.
eventMismatchError
||
this
.
eventMismatchError
||
Object
.
values
(
this
.
errors
).
some
(
errArray
=>
errArray
?.
length
)
Object
.
values
(
this
.
fieldErrors
).
some
(
errArray
=>
errArray
?.
length
)
);
);
},
},
isComplete
()
{
isComplete
()
{
...
@@ -162,7 +156,7 @@ export default {
...
@@ -162,7 +156,7 @@ export default {
);
);
},
},
isDirty
()
{
isDirty
()
{
return
!
isEqual
(
this
.
initialFields
,
this
.
fields
)
&&
!
isEqual
(
defaultFields
,
this
.
f
ields
);
return
!
isEqual
(
this
.
fields
,
this
.
formInitialData
||
defaultF
ields
);
},
},
eventMismatchError
()
{
eventMismatchError
()
{
const
{
const
{
...
@@ -188,35 +182,39 @@ export default {
...
@@ -188,35 +182,39 @@ export default {
},
},
},
},
watch
:
{
watch
:
{
initialFields
(
newFields
)
{
formInitialData
(
newFields
=
{}
)
{
this
.
fields
=
{
this
.
fields
=
{
...
defaultFields
,
...
defaultFields
,
...
newFields
,
...
newFields
,
};
};
},
},
errors
(
newErrors
)
{
formErrors
(
newErrors
=
{})
{
this
.
fieldErrors
=
{
this
.
errors
=
{
...
defaultFields
,
...
newErrors
,
...
newErrors
,
};
};
},
},
},
},
mounted
()
{
this
.
resetFields
();
},
methods
:
{
methods
:
{
handleCancel
()
{
resetFields
()
{
const
{
initialFields
=
{},
errors
=
null
}
=
this
;
const
{
formInitialData
,
formErrors
}
=
this
;
const
formData
=
initializeFormData
({
const
{
fields
,
errors
}
=
initializeFormData
({
emptyFieldState
:
defaultFields
,
fields
:
formInitialData
,
initialFields
,
errors
:
formErrors
,
errors
,
});
});
this
.
$set
(
this
,
'
fields
'
,
formData
.
fields
);
this
.
fields
=
{
...
fields
};
this
.
$set
(
this
,
'
fieldErrors
'
,
formData
.
fieldErrors
);
this
.
errors
=
{
...
errors
};
},
handleCancel
()
{
this
.
resetFields
();
this
.
$emit
(
'
cancel
'
);
this
.
$emit
(
'
cancel
'
);
},
},
handleSave
()
{
handleSave
()
{
const
data
=
convertObjectPropsToSnakeCase
(
this
.
fields
);
const
data
=
convertObjectPropsToSnakeCase
(
this
.
fields
);
if
(
this
.
isEditingCustomStage
)
{
if
(
this
.
isEditingCustomStage
)
{
const
{
id
}
=
this
.
initialF
ields
;
const
{
id
}
=
this
.
f
ields
;
this
.
$emit
(
STAGE_ACTIONS
.
UPDATE
,
{
...
data
,
id
});
this
.
$emit
(
STAGE_ACTIONS
.
UPDATE
,
{
...
data
,
id
});
}
else
{
}
else
{
this
.
$emit
(
STAGE_ACTIONS
.
CREATE
,
data
);
this
.
$emit
(
STAGE_ACTIONS
.
CREATE
,
data
);
...
@@ -229,31 +227,22 @@ export default {
...
@@ -229,31 +227,22 @@ export default {
this
.
fields
[
key
]
=
null
;
this
.
fields
[
key
]
=
null
;
},
},
hasFieldErrors
(
key
)
{
hasFieldErrors
(
key
)
{
return
this
.
fieldE
rrors
[
key
]?.
length
>
0
;
return
this
.
e
rrors
[
key
]?.
length
>
0
;
},
},
fieldErrorMessage
(
key
)
{
fieldErrorMessage
(
key
)
{
return
this
.
fieldE
rrors
[
key
]?.
join
(
'
\n
'
);
return
this
.
e
rrors
[
key
]?.
join
(
'
\n
'
);
},
},
onUpdateNameField
()
{
onUpdateNameField
()
{
if
(
DEFAULT_STAGE_NAMES
.
includes
(
this
.
fields
.
name
.
toLowerCase
()))
{
this
.
errors
.
name
=
DEFAULT_STAGE_NAMES
.
includes
(
this
.
fields
.
name
.
toLowerCase
())
this
.
$set
(
this
.
fieldErrors
,
'
name
'
,
[
?
[
ERRORS
.
STAGE_NAME_EXISTS
]
s__
(
'
CustomCycleAnalytics|Stage name already exists
'
),
:
[];
]);
}
else
{
this
.
$set
(
this
.
fieldErrors
,
'
name
'
,
[]);
}
},
},
onUpdateStartEventField
()
{
onUpdateStartEventField
()
{
const
initVal
=
this
.
initialFields
?.
endEventIdentifier
this
.
fields
.
endEventIdentifier
=
null
;
?
this
.
initialFields
.
endEventIdentifier
this
.
errors
.
endEventIdentifier
=
[
ERRORS
.
INVALID_EVENT_PAIRS
];
:
null
;
this
.
$set
(
this
.
fields
,
'
endEventIdentifier
'
,
initVal
);
this
.
$set
(
this
.
fieldErrors
,
'
endEventIdentifier
'
,
[
s__
(
'
CustomCycleAnalytics|Start event changed, please select a valid stop event
'
),
]);
},
},
onUpdateEndEventField
()
{
onUpdateEndEventField
()
{
this
.
$set
(
this
.
fieldErrors
,
'
endEventIdentifier
'
,
null
)
;
this
.
errors
.
endEventIdentifier
=
[]
;
},
},
handleRecoverStage
(
id
)
{
handleRecoverStage
(
id
)
{
this
.
$emit
(
STAGE_ACTIONS
.
UPDATE
,
{
id
,
hidden
:
false
});
this
.
$emit
(
STAGE_ACTIONS
.
UPDATE
,
{
id
,
hidden
:
false
});
...
@@ -262,7 +251,10 @@ export default {
...
@@ -262,7 +251,10 @@ export default {
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<form
class=
"custom-stage-form m-4 mt-0"
>
<div
v-if=
"isLoading"
>
<gl-loading-icon
class=
"mt-4"
size=
"md"
/>
</div>
<form
v-else
class=
"custom-stage-form m-4 mt-0"
>
<div
class=
"mb-1 d-flex flex-row justify-content-between"
>
<div
class=
"mb-1 d-flex flex-row justify-content-between"
>
<h4>
{{
formTitle
}}
</h4>
<h4>
{{
formTitle
}}
</h4>
<gl-dropdown
:text=
"__('Recover hidden stage')"
class=
"js-recover-hidden-stage-dropdown"
>
<gl-dropdown
:text=
"__('Recover hidden stage')"
class=
"js-recover-hidden-stage-dropdown"
>
...
@@ -366,7 +358,6 @@ export default {
...
@@ -366,7 +358,6 @@ export default {
</gl-form-group>
</gl-form-group>
</div>
</div>
</div>
</div>
<div
class=
"custom-stage-form-actions"
>
<div
class=
"custom-stage-form-actions"
>
<button
<button
:disabled=
"!isDirty"
:disabled=
"!isDirty"
...
@@ -386,7 +377,6 @@ export default {
...
@@ -386,7 +377,6 @@ export default {
{{ saveStageText }}
{{ saveStageText }}
</button>
</button>
</div>
</div>
<div
class=
"mt-2"
>
<div
class=
"mt-2"
>
<gl-sprintf
<gl-sprintf
:message=
"
:message=
"
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/components/stage_table_nav.vue
View file @
817f6d4d
...
@@ -29,10 +29,6 @@ export default {
...
@@ -29,10 +29,6 @@ export default {
type
:
Boolean
,
type
:
Boolean
,
required
:
true
,
required
:
true
,
},
},
customStageFormActive
:
{
type
:
Boolean
,
required
:
true
,
},
canEditStages
:
{
canEditStages
:
{
type
:
Boolean
,
type
:
Boolean
,
required
:
true
,
required
:
true
,
...
@@ -106,7 +102,7 @@ export default {
...
@@ -106,7 +102,7 @@ export default {
<add-stage-button
<add-stage-button
v-if=
"canEditStages"
v-if=
"canEditStages"
:class=
"$options.noDragClass"
:class=
"$options.noDragClass"
:active=
"
customStageFormActiv
e"
:active=
"
isCreatingCustomStag
e"
@
showform=
"$emit('showAddStageForm')"
@
showform=
"$emit('showAddStageForm')"
/>
/>
</ul>
</ul>
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/actions.js
View file @
817f6d4d
...
@@ -15,15 +15,18 @@ export const hideForm = ({ commit }) => {
...
@@ -15,15 +15,18 @@ export const hideForm = ({ commit }) => {
};
};
export
const
showCreateForm
=
({
commit
})
=>
{
export
const
showCreateForm
=
({
commit
})
=>
{
commit
(
types
.
SET_LOADING
);
commit
(
types
.
SET_FORM_INITIAL_DATA
);
commit
(
types
.
SHOW_CREATE_FORM
);
commit
(
types
.
SHOW_CREATE_FORM
);
removeFlash
();
removeFlash
();
};
};
export
const
showEditForm
=
({
commit
,
dispatch
},
selectedStage
=
{})
=>
{
export
const
showEditForm
=
({
commit
,
dispatch
},
selectedStage
=
{})
=>
{
commit
(
types
.
SET_LOADING
);
commit
(
types
.
SET_FORM_INITIAL_DATA
,
selectedStage
);
commit
(
types
.
SET_FORM_INITIAL_DATA
,
selectedStage
);
commit
(
types
.
SHOW_EDIT_FORM
);
dispatch
(
'
setSelectedStage
'
,
selectedStage
,
{
root
:
true
});
dispatch
(
'
setSelectedStage
'
,
selectedStage
,
{
root
:
true
});
dispatch
(
'
clearSavingCustomStage
'
);
dispatch
(
'
clearSavingCustomStage
'
);
commit
(
types
.
SHOW_EDIT_FORM
);
removeFlash
();
removeFlash
();
};
};
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/mutation_types.js
View file @
817f6d4d
export
const
SET_LOADING
=
'
SET_LOADING
'
;
export
const
SET_STAGE_EVENTS
=
'
SET_STAGE_EVENTS
'
;
export
const
SET_STAGE_EVENTS
=
'
SET_STAGE_EVENTS
'
;
export
const
SET_STAGE_FORM_ERRORS
=
'
SET_STAGE_FORM_ERRORS
'
;
export
const
SET_STAGE_FORM_ERRORS
=
'
SET_STAGE_FORM_ERRORS
'
;
export
const
SET_FORM_INITIAL_DATA
=
'
SET_FORM_INITIAL_DATA
'
;
export
const
SET_FORM_INITIAL_DATA
=
'
SET_FORM_INITIAL_DATA
'
;
export
const
SET_SAVING_CUSTOM_STAGE
=
'
SET_SAVING_CUSTOM_STAGE
'
;
export
const
SET_SAVING_CUSTOM_STAGE
=
'
SET_SAVING_CUSTOM_STAGE
'
;
export
const
CLEAR_SAVING_CUSTOM_STAGE
=
'
CLEAR_SAVING_CUSTOM_STAGE
'
;
export
const
CLEAR_SAVING_CUSTOM_STAGE
=
'
CLEAR_SAVING_CUSTOM_STAGE
'
;
export
const
HIDE_FORM
=
'
SHOW
_FORM
'
;
export
const
HIDE_FORM
=
'
HIDE
_FORM
'
;
export
const
SHOW_CREATE_FORM
=
'
SHOW_CREATE_FORM
'
;
export
const
SHOW_CREATE_FORM
=
'
SHOW_CREATE_FORM
'
;
export
const
SHOW_EDIT_FORM
=
'
SHOW_EDIT_FORM
'
;
export
const
SHOW_EDIT_FORM
=
'
SHOW_EDIT_FORM
'
;
export
const
CLEAR_FORM_ERRORS
=
'
CLEAR_FORM_ERRORS
'
;
export
const
CLEAR_FORM_ERRORS
=
'
CLEAR_FORM_ERRORS
'
;
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/mutations.js
View file @
817f6d4d
...
@@ -31,21 +31,26 @@ export default {
...
@@ -31,21 +31,26 @@ export default {
state
.
formErrors
=
convertObjectPropsToCamelCase
(
errors
,
{
deep
:
true
});
state
.
formErrors
=
convertObjectPropsToCamelCase
(
errors
,
{
deep
:
true
});
},
},
[
types
.
SET_FORM_INITIAL_DATA
](
state
,
rawStageData
=
null
)
{
[
types
.
SET_FORM_INITIAL_DATA
](
state
,
rawStageData
=
null
)
{
state
.
formInitialData
=
extractFormFields
(
rawStageData
)
;
state
.
formInitialData
=
rawStageData
?
extractFormFields
(
rawStageData
)
:
null
;
},
},
[
types
.
SET_SAVING_CUSTOM_STAGE
](
state
)
{
[
types
.
SET_SAVING_CUSTOM_STAGE
](
state
)
{
state
.
isSavingCustomStage
=
true
;
state
.
isSavingCustomStage
=
true
;
},
},
[
types
.
SET_LOADING
](
state
)
{
state
.
isLoadingCustomStage
=
true
;
},
[
types
.
CLEAR_SAVING_CUSTOM_STAGE
](
state
)
{
[
types
.
CLEAR_SAVING_CUSTOM_STAGE
](
state
)
{
state
.
isSavingCustomStage
=
false
;
state
.
isSavingCustomStage
=
false
;
},
},
[
types
.
SHOW_CREATE_FORM
](
state
)
{
[
types
.
SHOW_CREATE_FORM
](
state
)
{
state
.
isLoadingCustomStage
=
false
;
state
.
isEditingCustomStage
=
false
;
state
.
isEditingCustomStage
=
false
;
state
.
isCreatingCustomStage
=
true
;
state
.
isCreatingCustomStage
=
true
;
state
.
formInitialData
=
null
;
state
.
formInitialData
=
null
;
state
.
formErrors
=
null
;
state
.
formErrors
=
null
;
},
},
[
types
.
SHOW_EDIT_FORM
](
state
)
{
[
types
.
SHOW_EDIT_FORM
](
state
)
{
state
.
isLoadingCustomStage
=
false
;
state
.
isCreatingCustomStage
=
false
;
state
.
isCreatingCustomStage
=
false
;
state
.
isEditingCustomStage
=
true
;
state
.
isEditingCustomStage
=
true
;
state
.
formErrors
=
null
;
state
.
formErrors
=
null
;
...
...
ee/app/assets/javascripts/analytics/cycle_analytics/store/modules/custom_stages/state.js
View file @
817f6d4d
export
default
()
=>
({
export
default
()
=>
({
isLoadingCustomStage
:
false
,
isSavingCustomStage
:
false
,
isSavingCustomStage
:
false
,
isCreatingCustomStage
:
false
,
isCreatingCustomStage
:
false
,
isEditingCustomStage
:
false
,
isEditingCustomStage
:
false
,
...
...
ee/spec/frontend/analytics/cycle_analytics/components/custom_stage_form_spec.js
View file @
817f6d4d
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
Vuex
from
'
vuex
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
c
reateStore
from
'
ee/analytics/cycle_analytics/store
'
;
import
c
ustomStagesStore
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages
'
;
import
{
createLocalVue
,
mount
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
,
mount
}
from
'
@vue/test-utils
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
CustomStageForm
,
{
import
CustomStageForm
,
{
...
@@ -20,7 +19,7 @@ import {
...
@@ -20,7 +19,7 @@ import {
customStageFormErrors
,
customStageFormErrors
,
}
from
'
../mock_data
'
;
}
from
'
../mock_data
'
;
const
init
Data
=
{
const
formInitial
Data
=
{
id
:
74
,
id
:
74
,
name
:
'
Cool stage pre
'
,
name
:
'
Cool stage pre
'
,
startEventIdentifier
:
labelStartEvent
.
identifier
,
startEventIdentifier
:
labelStartEvent
.
identifier
,
...
@@ -32,16 +31,37 @@ const initData = {
...
@@ -32,16 +31,37 @@ const initData = {
const
MERGE_REQUEST_CREATED
=
'
merge_request_created
'
;
const
MERGE_REQUEST_CREATED
=
'
merge_request_created
'
;
const
MERGE_REQUEST_CLOSED
=
'
merge_request_closed
'
;
const
MERGE_REQUEST_CLOSED
=
'
merge_request_closed
'
;
let
store
=
null
;
const
localVue
=
createLocalVue
();
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
localVue
.
use
(
Vuex
);
const
fakeStore
=
({
initialState
,
initialRootGetters
})
=>
new
Vuex
.
Store
({
getters
:
{
currentGroupPath
:
()
=>
'
fake
'
,
hiddenStages
:
()
=>
[],
...
initialRootGetters
,
},
modules
:
{
customStages
:
{
...
customStagesStore
,
state
:
{
isLoading
:
false
,
...
initialState
,
},
},
},
});
describe
(
'
CustomStageForm
'
,
()
=>
{
describe
(
'
CustomStageForm
'
,
()
=>
{
function
createComponent
(
props
=
{},
stubs
=
{})
{
function
createComponent
({
store
=
createStore
();
initialState
=
{},
initialRootGetters
=
{},
stubs
=
{},
props
=
{},
}
=
{})
{
return
mount
(
CustomStageForm
,
{
return
mount
(
CustomStageForm
,
{
localVue
,
localVue
,
store
,
store
:
fakeStore
({
initialState
,
initialRootGetters
})
,
propsData
:
{
propsData
:
{
events
,
events
,
...
props
,
...
props
,
...
@@ -98,7 +118,7 @@ describe('CustomStageForm', () => {
...
@@ -98,7 +118,7 @@ describe('CustomStageForm', () => {
stopEventDropdownIndex
=
mergeRequestClosedDropdownIndex
,
stopEventDropdownIndex
=
mergeRequestClosedDropdownIndex
,
}
=
{})
{
}
=
{})
{
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
selectDropdownOption
(
wrapper
,
sel
.
endEvent
,
stopEventDropdownIndex
);
selectDropdownOption
(
wrapper
,
sel
.
endEvent
,
stopEventDropdownIndex
);
});
});
}
}
...
@@ -117,7 +137,7 @@ describe('CustomStageForm', () => {
...
@@ -117,7 +137,7 @@ describe('CustomStageForm', () => {
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mock
=
mockGroupLabelsRequest
();
mock
=
mockGroupLabelsRequest
();
wrapper
=
createComponent
(
{}
);
wrapper
=
createComponent
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -155,7 +175,7 @@ describe('CustomStageForm', () => {
...
@@ -155,7 +175,7 @@ describe('CustomStageForm', () => {
describe
(
'
Name
'
,
()
=>
{
describe
(
'
Name
'
,
()
=>
{
describe
(
'
with a reserved name
'
,
()
=>
{
describe
(
'
with a reserved name
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
(
{}
);
wrapper
=
createComponent
();
return
setNameField
(
wrapper
,
'
issue
'
);
return
setNameField
(
wrapper
,
'
issue
'
);
});
});
...
@@ -174,7 +194,7 @@ describe('CustomStageForm', () => {
...
@@ -174,7 +194,7 @@ describe('CustomStageForm', () => {
describe
(
'
Start event
'
,
()
=>
{
describe
(
'
Start event
'
,
()
=>
{
describe
(
'
with events
'
,
()
=>
{
describe
(
'
with events
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
(
{}
);
wrapper
=
createComponent
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -229,7 +249,7 @@ describe('CustomStageForm', () => {
...
@@ -229,7 +249,7 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
sel
.
startEventLabel
).
exists
()).
toEqual
(
true
);
expect
(
wrapper
.
find
(
sel
.
startEventLabel
).
exists
()).
toEqual
(
true
);
});
});
});
});
...
@@ -246,7 +266,7 @@ describe('CustomStageForm', () => {
...
@@ -246,7 +266,7 @@ describe('CustomStageForm', () => {
.
findAll
(
'
.dropdown-item
'
)
.
findAll
(
'
.dropdown-item
'
)
.
at
(
1
)
// item at index 0 is 'select a label'
.
at
(
1
)
// item at index 0 is 'select a label'
.
trigger
(
'
click
'
);
.
trigger
(
'
click
'
);
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
wrapper
.
vm
.
fields
.
startEventLabelId
).
toEqual
(
selectedLabelId
);
expect
(
wrapper
.
vm
.
fields
.
startEventLabelId
).
toEqual
(
selectedLabelId
);
...
@@ -265,12 +285,14 @@ describe('CustomStageForm', () => {
...
@@ -265,12 +285,14 @@ describe('CustomStageForm', () => {
});
});
it
(
'
notifies that a start event needs to be selected first
'
,
()
=>
{
it
(
'
notifies that a start event needs to be selected first
'
,
()
=>
{
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
text
()).
toContain
(
'
Please select a start event first
'
);
expect
(
wrapper
.
text
()).
toContain
(
'
Please select a start event first
'
);
});
});
});
it
(
'
clears notification when a start event is selected
'
,
()
=>
{
it
(
'
clears notification when a start event is selected
'
,
()
=>
{
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
wrapper
.
text
()).
not
.
toContain
(
'
Please select a start event first
'
);
expect
(
wrapper
.
text
()).
not
.
toContain
(
'
Please select a start event first
'
);
});
});
});
});
...
@@ -280,7 +302,7 @@ describe('CustomStageForm', () => {
...
@@ -280,7 +302,7 @@ describe('CustomStageForm', () => {
expect
(
el
.
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
expect
(
el
.
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
el
.
attributes
(
'
disabled
'
)).
toBeUndefined
();
expect
(
el
.
attributes
(
'
disabled
'
)).
toBeUndefined
();
});
});
});
});
...
@@ -292,7 +314,7 @@ describe('CustomStageForm', () => {
...
@@ -292,7 +314,7 @@ describe('CustomStageForm', () => {
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
stopOptions
=
wrapper
.
find
(
sel
.
endEvent
);
stopOptions
=
wrapper
.
find
(
sel
.
endEvent
);
selectedStartEvent
.
allowedEndEvents
.
forEach
(
identifier
=>
{
selectedStartEvent
.
allowedEndEvents
.
forEach
(
identifier
=>
{
expect
(
stopOptions
.
html
()).
toContain
(
identifier
);
expect
(
stopOptions
.
html
()).
toContain
(
identifier
);
...
@@ -308,7 +330,7 @@ describe('CustomStageForm', () => {
...
@@ -308,7 +330,7 @@ describe('CustomStageForm', () => {
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventDropdownIndex
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
stopOptions
=
wrapper
.
find
(
sel
.
endEvent
);
stopOptions
=
wrapper
.
find
(
sel
.
endEvent
);
possibleEndEvents
.
forEach
(({
name
,
identifier
})
=>
{
possibleEndEvents
.
forEach
(({
name
,
identifier
})
=>
{
...
@@ -325,7 +347,7 @@ describe('CustomStageForm', () => {
...
@@ -325,7 +347,7 @@ describe('CustomStageForm', () => {
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventArrayIndex
+
1
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
startEventArrayIndex
+
1
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
stopOptions
=
wrapper
.
find
(
sel
.
endEvent
);
stopOptions
=
wrapper
.
find
(
sel
.
endEvent
);
excludedEndEvents
.
forEach
(({
name
,
identifier
})
=>
{
excludedEndEvents
.
forEach
(({
name
,
identifier
})
=>
{
...
@@ -355,10 +377,16 @@ describe('CustomStageForm', () => {
...
@@ -355,10 +377,16 @@ describe('CustomStageForm', () => {
wrapper
.
destroy
();
wrapper
.
destroy
();
});
});
it
(
'
notifies that a start event needs to be selected first
'
,
()
=>
{
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
text
()).
toContain
(
'
Please select a start event first
'
);
});
});
it
(
'
will notify if the current start and stop event pair is not valid
'
,
()
=>
{
it
(
'
will notify if the current start and stop event pair is not valid
'
,
()
=>
{
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
2
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
2
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
sel
.
invalidFeedback
).
exists
()).
toEqual
(
true
);
expect
(
wrapper
.
find
(
sel
.
invalidFeedback
).
exists
()).
toEqual
(
true
);
expect
(
wrapper
.
find
(
sel
.
invalidFeedback
).
text
()).
toContain
(
expect
(
wrapper
.
find
(
sel
.
invalidFeedback
).
text
()).
toContain
(
'
Start event changed, please select a valid stop event
'
,
'
Start event changed, please select a valid stop event
'
,
...
@@ -369,14 +397,14 @@ describe('CustomStageForm', () => {
...
@@ -369,14 +397,14 @@ describe('CustomStageForm', () => {
it
(
'
will update the list of stop events
'
,
()
=>
{
it
(
'
will update the list of stop events
'
,
()
=>
{
const
se
=
wrapper
.
vm
.
endEventOptions
;
const
se
=
wrapper
.
vm
.
endEventOptions
;
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
2
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
2
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
se
[
1
].
value
).
not
.
toEqual
(
wrapper
.
vm
.
endEventOptions
[
1
].
value
);
expect
(
se
[
1
].
value
).
not
.
toEqual
(
wrapper
.
vm
.
endEventOptions
[
1
].
value
);
});
});
});
});
it
(
'
will disable the submit button until a valid endEvent is selected
'
,
()
=>
{
it
(
'
will disable the submit button until a valid endEvent is selected
'
,
()
=>
{
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
2
);
selectDropdownOption
(
wrapper
,
sel
.
startEvent
,
2
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
sel
.
submit
).
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
expect
(
wrapper
.
find
(
sel
.
submit
).
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
});
});
});
});
...
@@ -384,7 +412,7 @@ describe('CustomStageForm', () => {
...
@@ -384,7 +412,7 @@ describe('CustomStageForm', () => {
describe
(
'
Stop event label
'
,
()
=>
{
describe
(
'
Stop event label
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
(
{}
);
wrapper
=
createComponent
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -405,7 +433,7 @@ describe('CustomStageForm', () => {
...
@@ -405,7 +433,7 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
sel
.
endEventLabel
).
exists
()).
toEqual
(
true
);
expect
(
wrapper
.
find
(
sel
.
endEventLabel
).
exists
()).
toEqual
(
true
);
});
});
});
});
...
@@ -429,7 +457,7 @@ describe('CustomStageForm', () => {
...
@@ -429,7 +457,7 @@ describe('CustomStageForm', () => {
.
at
(
2
)
// item at index 0 is 'select a label'
.
at
(
2
)
// item at index 0 is 'select a label'
.
trigger
(
'
click
'
);
.
trigger
(
'
click
'
);
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
wrapper
.
vm
.
fields
.
endEventLabelId
).
toEqual
(
selectedLabelId
);
expect
(
wrapper
.
vm
.
fields
.
endEventLabelId
).
toEqual
(
selectedLabelId
);
...
@@ -440,7 +468,7 @@ describe('CustomStageForm', () => {
...
@@ -440,7 +468,7 @@ describe('CustomStageForm', () => {
describe
(
'
Add stage button
'
,
()
=>
{
describe
(
'
Add stage button
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
(
{}
);
wrapper
=
createComponent
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -468,11 +496,11 @@ describe('CustomStageForm', () => {
...
@@ -468,11 +496,11 @@ describe('CustomStageForm', () => {
const
stopEventDropdownIndex
=
1
;
const
stopEventDropdownIndex
=
1
;
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
(
{}
);
wrapper
=
createComponent
();
wrapper
.
find
(
sel
.
name
).
setValue
(
'
Cool stage
'
);
wrapper
.
find
(
sel
.
name
).
setValue
(
'
Cool stage
'
);
return
Vue
.
nextTick
().
then
(()
=>
return
wrapper
.
vm
setEventDropdowns
({
startEventDropdownIndex
,
stopEventDropdownIndex
}),
.
$nextTick
()
);
.
then
(()
=>
setEventDropdowns
({
startEventDropdownIndex
,
stopEventDropdownIndex
})
);
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -485,7 +513,7 @@ describe('CustomStageForm', () => {
...
@@ -485,7 +513,7 @@ describe('CustomStageForm', () => {
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
event
=
findEvent
(
STAGE_ACTIONS
.
CREATE
);
event
=
findEvent
(
STAGE_ACTIONS
.
CREATE
);
expect
(
event
).
toBeTruthy
();
expect
(
event
).
toBeTruthy
();
expect
(
event
).
toHaveLength
(
1
);
expect
(
event
).
toHaveLength
(
1
);
...
@@ -510,7 +538,7 @@ describe('CustomStageForm', () => {
...
@@ -510,7 +538,7 @@ describe('CustomStageForm', () => {
];
];
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
event
=
findEvent
(
STAGE_ACTIONS
.
CREATE
);
event
=
findEvent
(
STAGE_ACTIONS
.
CREATE
);
expect
(
event
[
0
]).
toEqual
(
res
);
expect
(
event
[
0
]).
toEqual
(
res
);
});
});
...
@@ -520,7 +548,7 @@ describe('CustomStageForm', () => {
...
@@ -520,7 +548,7 @@ describe('CustomStageForm', () => {
describe
(
'
Cancel button
'
,
()
=>
{
describe
(
'
Cancel button
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
(
{}
);
wrapper
=
createComponent
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -533,7 +561,7 @@ describe('CustomStageForm', () => {
...
@@ -533,7 +561,7 @@ describe('CustomStageForm', () => {
expect
(
btn
.
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
expect
(
btn
.
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
wrapper
.
find
(
sel
.
name
).
setValue
(
'
Cool stage
'
);
wrapper
.
find
(
sel
.
name
).
setValue
(
'
Cool stage
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
btn
.
attributes
(
'
disabled
'
)).
toBeUndefined
();
expect
(
btn
.
attributes
(
'
disabled
'
)).
toBeUndefined
();
});
});
});
});
...
@@ -547,11 +575,12 @@ describe('CustomStageForm', () => {
...
@@ -547,11 +575,12 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
()
return
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
wrapper
.
find
(
sel
.
cancel
).
trigger
(
'
click
'
);
wrapper
.
find
(
sel
.
cancel
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
wrapper
.
vm
.
fields
).
toEqual
({
expect
(
wrapper
.
vm
.
fields
).
toEqual
({
...
@@ -575,10 +604,11 @@ describe('CustomStageForm', () => {
...
@@ -575,10 +604,11 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
()
return
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
wrapper
.
find
(
sel
.
cancel
).
trigger
(
'
click
'
);
wrapper
.
find
(
sel
.
cancel
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
ev
=
findEvent
(
'
cancel
'
);
ev
=
findEvent
(
'
cancel
'
);
...
@@ -590,12 +620,12 @@ describe('CustomStageForm', () => {
...
@@ -590,12 +620,12 @@ describe('CustomStageForm', () => {
describe
(
'
isSavingCustomStage=true
'
,
()
=>
{
describe
(
'
isSavingCustomStage=true
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
(
wrapper
=
createComponent
(
{
{
initialState
:
{
isSavingCustomStage
:
true
,
isSavingCustomStage
:
true
,
},
},
false
,
});
);
return
wrapper
.
vm
.
$nextTick
(
);
});
});
it
(
'
displays a loading icon
'
,
()
=>
{
it
(
'
displays a loading icon
'
,
()
=>
{
...
@@ -606,19 +636,13 @@ describe('CustomStageForm', () => {
...
@@ -606,19 +636,13 @@ describe('CustomStageForm', () => {
describe
(
'
Editing a custom stage
'
,
()
=>
{
describe
(
'
Editing a custom stage
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
wrapper
=
createComponent
({
initialState
:
{
isEditingCustomStage
:
true
,
isEditingCustomStage
:
true
,
initialFields
:
{
formInitialData
,
...
initData
,
},
},
});
});
wrapper
.
setData
({
return
wrapper
.
vm
.
$nextTick
();
fields
:
{
...
initData
,
},
});
return
Vue
.
nextTick
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -635,13 +659,14 @@ describe('CustomStageForm', () => {
...
@@ -635,13 +659,14 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
()
return
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
wrapper
.
find
(
sel
.
cancel
).
trigger
(
'
click
'
);
wrapper
.
find
(
sel
.
cancel
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
wrapper
.
vm
.
fields
).
toEqual
({
...
init
Data
});
expect
(
wrapper
.
vm
.
fields
).
toEqual
({
...
formInitial
Data
});
});
});
});
});
});
});
...
@@ -662,7 +687,7 @@ describe('CustomStageForm', () => {
...
@@ -662,7 +687,7 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
sel
.
submit
).
attributes
(
'
disabled
'
)).
toBeUndefined
();
expect
(
wrapper
.
find
(
sel
.
submit
).
attributes
(
'
disabled
'
)).
toBeUndefined
();
});
});
});
});
...
@@ -674,7 +699,7 @@ describe('CustomStageForm', () => {
...
@@ -674,7 +699,7 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
().
then
(()
=>
{
return
wrapper
.
vm
.
$
nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
sel
.
submit
).
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
expect
(
wrapper
.
find
(
sel
.
submit
).
attributes
(
'
disabled
'
)).
toEqual
(
'
disabled
'
);
});
});
});
});
...
@@ -689,10 +714,11 @@ describe('CustomStageForm', () => {
...
@@ -689,10 +714,11 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
()
return
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
ev
=
findEvent
(
STAGE_ACTIONS
.
UPDATE
);
ev
=
findEvent
(
STAGE_ACTIONS
.
UPDATE
);
...
@@ -708,17 +734,18 @@ describe('CustomStageForm', () => {
...
@@ -708,17 +734,18 @@ describe('CustomStageForm', () => {
},
},
});
});
return
Vue
.
nextTick
()
return
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
wrapper
.
find
(
sel
.
submit
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
const
submitted
=
findEvent
(
STAGE_ACTIONS
.
UPDATE
)[
0
];
const
submitted
=
findEvent
(
STAGE_ACTIONS
.
UPDATE
)[
0
];
expect
(
submitted
).
not
.
toEqual
([
init
Data
]);
expect
(
submitted
).
not
.
toEqual
([
formInitial
Data
]);
expect
(
submitted
).
toEqual
([
expect
(
submitted
).
toEqual
([
{
{
id
:
init
Data
.
id
,
id
:
formInitial
Data
.
id
,
start_event_identifier
:
labelStartEvent
.
identifier
,
start_event_identifier
:
labelStartEvent
.
identifier
,
start_event_label_id
:
groupLabels
[
0
].
id
,
start_event_label_id
:
groupLabels
[
0
].
id
,
end_event_identifier
:
labelStopEvent
.
identifier
,
end_event_identifier
:
labelStopEvent
.
identifier
,
...
@@ -733,11 +760,10 @@ describe('CustomStageForm', () => {
...
@@ -733,11 +760,10 @@ describe('CustomStageForm', () => {
describe
(
'
isSavingCustomStage=true
'
,
()
=>
{
describe
(
'
isSavingCustomStage=true
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
wrapper
=
createComponent
({
initialState
:
{
isEditingCustomStage
:
true
,
isEditingCustomStage
:
true
,
initialFields
:
{
...
initData
,
},
isSavingCustomStage
:
true
,
isSavingCustomStage
:
true
,
},
});
});
});
});
it
(
'
displays a loading icon
'
,
()
=>
{
it
(
'
displays a loading icon
'
,
()
=>
{
...
@@ -749,11 +775,12 @@ describe('CustomStageForm', () => {
...
@@ -749,11 +775,12 @@ describe('CustomStageForm', () => {
describe
(
'
With errors
'
,
()
=>
{
describe
(
'
With errors
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
wrapper
=
createComponent
({
initialFields
:
initData
,
initialState
:
{
errors
:
customStageFormErrors
,
formErrors
:
customStageFormErrors
,
},
});
});
return
Vue
.
nextTick
();
return
wrapper
.
vm
.
$
nextTick
();
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -775,7 +802,9 @@ describe('CustomStageForm', () => {
...
@@ -775,7 +802,9 @@ describe('CustomStageForm', () => {
};
};
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({},
formFieldStubs
);
wrapper
=
createComponent
({
stubs
:
formFieldStubs
,
});
});
});
describe
(
'
without hidden stages
'
,
()
=>
{
describe
(
'
without hidden stages
'
,
()
=>
{
...
@@ -795,8 +824,12 @@ describe('CustomStageForm', () => {
...
@@ -795,8 +824,12 @@ describe('CustomStageForm', () => {
describe
(
'
with hidden stages
'
,
()
=>
{
describe
(
'
with hidden stages
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({},
formFieldStubs
);
wrapper
=
createComponent
({
store
.
state
.
stages
=
[{
id
:
'
my-stage
'
,
title
:
'
My default stage
'
,
hidden
:
true
}];
stubs
:
formFieldStubs
,
initialRootGetters
:
{
hiddenStages
:
()
=>
[{
id
:
'
my-stage
'
,
title
:
'
My default stage
'
,
hidden
:
true
}],
},
});
});
});
it
(
'
has stages available to recover
'
,
()
=>
{
it
(
'
has stages available to recover
'
,
()
=>
{
...
@@ -825,26 +858,46 @@ describe('CustomStageForm', () => {
...
@@ -825,26 +858,46 @@ describe('CustomStageForm', () => {
});
});
describe
(
'
initializeFormData
'
,
()
=>
{
describe
(
'
initializeFormData
'
,
()
=>
{
const
emptyFieldState
=
{
id
:
null
,
name
:
null
,
startEventIdentifier
:
null
,
startEventLabelId
:
null
,
endEventIdentifier
:
null
,
endEventLabelId
:
null
,
};
const
emptyErrorsState
=
{
id
:
[],
name
:
[],
startEventIdentifier
:
[],
startEventLabelId
:
[],
endEventIdentifier
:
[],
endEventLabelId
:
[],
};
describe
(
'
without a startEventIdentifier
'
,
()
=>
{
describe
(
'
without a startEventIdentifier
'
,
()
=>
{
it
(
'
with no errors
'
,
()
=>
{
it
(
'
with no errors
'
,
()
=>
{
const
res
=
initializeFormData
({
const
res
=
initializeFormData
({
initialFields
:
{},
emptyFieldState
,
fields
:
{},
});
});
expect
(
res
.
fields
).
toEqual
(
{}
);
expect
(
res
.
fields
).
toEqual
(
emptyFieldState
);
expect
(
res
.
fieldErrors
).
toEqual
({
expect
(
res
.
errors
).
toMatchObject
({
endEventIdentifier
:
[
'
Please select a start event first
'
],
endEventIdentifier
:
[
'
Please select a start event first
'
],
});
});
});
});
it
(
'
with field errors
'
,
()
=>
{
it
(
'
with field errors
'
,
()
=>
{
const
res
=
initializeFormData
({
const
res
=
initializeFormData
({
initialFields
:
{},
emptyFieldState
,
fields
:
{},
errors
:
{
errors
:
{
name
:
[
'
is reserved
'
],
name
:
[
'
is reserved
'
],
},
},
});
});
expect
(
res
.
fields
).
toEqual
(
{}
);
expect
(
res
.
fields
).
toEqual
(
emptyFieldState
);
expect
(
res
.
fieldErrors
).
toEqual
({
expect
(
res
.
errors
).
toMatchObject
({
endEventIdentifier
:
[
'
Please select a start event first
'
],
endEventIdentifier
:
[
'
Please select a start event first
'
],
name
:
[
'
is reserved
'
],
name
:
[
'
is reserved
'
],
});
});
...
@@ -854,29 +907,31 @@ describe('CustomStageForm', () => {
...
@@ -854,29 +907,31 @@ describe('CustomStageForm', () => {
describe
(
'
with a startEventIdentifier
'
,
()
=>
{
describe
(
'
with a startEventIdentifier
'
,
()
=>
{
it
(
'
with no errors
'
,
()
=>
{
it
(
'
with no errors
'
,
()
=>
{
const
res
=
initializeFormData
({
const
res
=
initializeFormData
({
initialFields
:
{
emptyFieldState
,
fields
:
{
startEventIdentifier
:
'
start-event
'
,
startEventIdentifier
:
'
start-event
'
,
},
},
errors
:
{},
errors
:
{},
});
});
expect
(
res
.
fields
).
toEqual
({
startEventIdentifier
:
'
start-event
'
});
expect
(
res
.
fields
).
toEqual
({
...
emptyFieldState
,
startEventIdentifier
:
'
start-event
'
});
expect
(
res
.
fieldErrors
).
toEqual
({
expect
(
res
.
errors
).
toMatchObject
({
endEventIdentifier
:
null
,
endEventIdentifier
:
[]
,
});
});
});
});
it
(
'
with field errors
'
,
()
=>
{
it
(
'
with field errors
'
,
()
=>
{
const
res
=
initializeFormData
({
const
res
=
initializeFormData
({
initialFields
:
{
emptyFieldState
,
fields
:
{
startEventIdentifier
:
'
start-event
'
,
startEventIdentifier
:
'
start-event
'
,
},
},
errors
:
{
errors
:
{
name
:
[
'
is reserved
'
],
name
:
[
'
is reserved
'
],
},
},
});
});
expect
(
res
.
fields
).
toEqual
({
startEventIdentifier
:
'
start-event
'
});
expect
(
res
.
fields
).
toEqual
({
...
emptyFieldState
,
startEventIdentifier
:
'
start-event
'
});
expect
(
res
.
fieldErrors
).
toEqual
({
expect
(
res
.
errors
).
toMatchObject
({
endEventIdentifier
:
null
,
endEventIdentifier
:
[]
,
name
:
[
'
is reserved
'
],
name
:
[
'
is reserved
'
],
});
});
});
});
...
@@ -885,7 +940,8 @@ describe('CustomStageForm', () => {
...
@@ -885,7 +940,8 @@ describe('CustomStageForm', () => {
describe
(
'
with all fields set
'
,
()
=>
{
describe
(
'
with all fields set
'
,
()
=>
{
it
(
'
with no errors
'
,
()
=>
{
it
(
'
with no errors
'
,
()
=>
{
const
res
=
initializeFormData
({
const
res
=
initializeFormData
({
initialFields
:
{
emptyFieldState
,
fields
:
{
id
:
1
,
id
:
1
,
name
:
'
cool-stage
'
,
name
:
'
cool-stage
'
,
startEventIdentifier
:
'
start-event
'
,
startEventIdentifier
:
'
start-event
'
,
...
@@ -903,14 +959,13 @@ describe('CustomStageForm', () => {
...
@@ -903,14 +959,13 @@ describe('CustomStageForm', () => {
startEventLabelId
:
10
,
startEventLabelId
:
10
,
endEventLabelId
:
20
,
endEventLabelId
:
20
,
});
});
expect
(
res
.
fieldErrors
).
toEqual
({
expect
(
res
.
errors
).
toEqual
(
emptyErrorsState
);
endEventIdentifier
:
null
,
});
});
});
it
(
'
with field errors
'
,
()
=>
{
it
(
'
with field errors
'
,
()
=>
{
const
res
=
initializeFormData
({
const
res
=
initializeFormData
({
initialFields
:
{
emptyFieldState
,
fields
:
{
id
:
1
,
id
:
1
,
name
:
'
cool-stage
'
,
name
:
'
cool-stage
'
,
startEventIdentifier
:
'
start-event
'
,
startEventIdentifier
:
'
start-event
'
,
...
@@ -922,6 +977,7 @@ describe('CustomStageForm', () => {
...
@@ -922,6 +977,7 @@ describe('CustomStageForm', () => {
name
:
[
'
is reserved
'
],
name
:
[
'
is reserved
'
],
},
},
});
});
expect
(
res
.
fields
).
toEqual
({
expect
(
res
.
fields
).
toEqual
({
id
:
1
,
id
:
1
,
name
:
'
cool-stage
'
,
name
:
'
cool-stage
'
,
...
@@ -930,8 +986,7 @@ describe('CustomStageForm', () => {
...
@@ -930,8 +986,7 @@ describe('CustomStageForm', () => {
startEventLabelId
:
10
,
startEventLabelId
:
10
,
endEventLabelId
:
20
,
endEventLabelId
:
20
,
});
});
expect
(
res
.
fieldErrors
).
toEqual
({
expect
(
res
.
errors
).
toMatchObject
({
endEventIdentifier
:
null
,
name
:
[
'
is reserved
'
],
name
:
[
'
is reserved
'
],
});
});
});
});
...
...
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
View file @
817f6d4d
...
@@ -130,8 +130,8 @@ export const rawCustomStage = {
...
@@ -130,8 +130,8 @@ export const rawCustomStage = {
export
const
medians
=
stageMedians
;
export
const
medians
=
stageMedians
;
const
{
events
:
rawCustomStageEvents
}
=
customizableStagesAndE
vents
;
export
const
rawCustomStageEvents
=
customizableStagesAndEvents
.
e
vents
;
const
camelCasedStageEvents
=
rawCustomStageEvents
.
map
(
deepCamelCase
);
export
const
camelCasedStageEvents
=
rawCustomStageEvents
.
map
(
deepCamelCase
);
export
const
customStageLabelEvents
=
camelCasedStageEvents
.
filter
(
ev
=>
ev
.
type
===
'
label
'
);
export
const
customStageLabelEvents
=
camelCasedStageEvents
.
filter
(
ev
=>
ev
.
type
===
'
label
'
);
export
const
customStageStartEvents
=
camelCasedStageEvents
.
filter
(
ev
=>
ev
.
canBeStartEvent
);
export
const
customStageStartEvents
=
camelCasedStageEvents
.
filter
(
ev
=>
ev
.
canBeStartEvent
);
...
...
ee/spec/frontend/analytics/cycle_analytics/store/actions_spec.js
View file @
817f6d4d
...
@@ -4,8 +4,6 @@ import testAction from 'helpers/vuex_action_helper';
...
@@ -4,8 +4,6 @@ import testAction from 'helpers/vuex_action_helper';
import
*
as
getters
from
'
ee/analytics/cycle_analytics/store/getters
'
;
import
*
as
getters
from
'
ee/analytics/cycle_analytics/store/getters
'
;
import
*
as
actions
from
'
ee/analytics/cycle_analytics/store/actions
'
;
import
*
as
actions
from
'
ee/analytics/cycle_analytics/store/actions
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/mutation_types
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/mutation_types
'
;
import
*
as
customStageActions
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/actions
'
;
import
*
as
customStageTypes
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/mutation_types
'
;
import
createFlash
from
'
~/flash
'
;
import
createFlash
from
'
~/flash
'
;
import
httpStatusCodes
from
'
~/lib/utils/http_status
'
;
import
httpStatusCodes
from
'
~/lib/utils/http_status
'
;
import
{
import
{
...
@@ -684,136 +682,6 @@ describe('Cycle analytics actions', () => {
...
@@ -684,136 +682,6 @@ describe('Cycle analytics actions', () => {
});
});
});
});
describe
(
'
createStage
'
,
()
=>
{
describe
(
'
with valid data
'
,
()
=>
{
const
customStageData
=
{
startEventIdentifier
:
'
start_event
'
,
endEventIdentifier
:
'
end_event
'
,
name
:
'
cool-new-stage
'
,
};
beforeEach
(()
=>
{
state
=
{
...
state
,
selectedGroup
};
mock
.
onPost
(
endpoints
.
baseStagesEndpointstageData
).
reply
(
201
,
customStageData
);
});
it
(
`dispatches the 'receiveCreateStageSuccess' action`
,
()
=>
testAction
(
customStageActions
.
createStage
,
customStageData
,
state
,
[],
[
{
type
:
'
clearFormErrors
'
},
{
type
:
'
setSavingCustomStage
'
},
{
type
:
'
receiveCreateStageSuccess
'
,
payload
:
{
data
:
customStageData
,
status
:
201
},
},
],
));
});
describe
(
'
with errors
'
,
()
=>
{
const
message
=
'
failed
'
;
const
errors
=
{
endEventIdentifier
:
[
'
Cant be blank
'
],
};
const
customStageData
=
{
startEventIdentifier
:
'
start_event
'
,
endEventIdentifier
:
''
,
name
:
'
cool-new-stage
'
,
};
beforeEach
(()
=>
{
state
=
{
...
state
,
selectedGroup
};
mock
.
onPost
(
endpoints
.
baseStagesEndpointstageData
)
.
reply
(
httpStatusCodes
.
UNPROCESSABLE_ENTITY
,
{
message
,
errors
,
});
});
it
(
`dispatches the 'receiveCreateStageError' action`
,
()
=>
testAction
(
customStageActions
.
createStage
,
customStageData
,
state
,
[],
[
{
type
:
'
clearFormErrors
'
},
{
type
:
'
setSavingCustomStage
'
},
{
type
:
'
receiveCreateStageError
'
,
payload
:
{
data
:
customStageData
,
errors
,
message
,
status
:
httpStatusCodes
.
UNPROCESSABLE_ENTITY
,
},
},
],
));
});
});
describe
(
'
receiveCreateStageError
'
,
()
=>
{
const
response
=
{
data
:
{
name
:
'
uh oh
'
},
};
beforeEach
(()
=>
{});
it
(
'
will commit the RECEIVE_CREATE_STAGE_ERROR mutation
'
,
()
=>
testAction
(
customStageActions
.
receiveCreateStageError
,
response
,
state
,
[{
type
:
customStageTypes
.
RECEIVE_CREATE_STAGE_ERROR
}],
[
{
type
:
'
setStageFormErrors
'
,
payload
:
{},
},
],
));
it
(
'
will flash an error message
'
,
()
=>
{
return
customStageActions
.
receiveCreateStageError
(
{
dispatch
:
()
=>
Promise
.
resolve
(),
commit
:
()
=>
{},
},
response
,
)
.
then
(()
=>
{
shouldFlashAMessage
(
'
There was a problem saving your custom stage, please try again
'
);
});
});
describe
(
'
with a stage name error
'
,
()
=>
{
it
(
'
will flash an error message
'
,
()
=>
{
return
customStageActions
.
receiveCreateStageError
(
{
dispatch
:
()
=>
Promise
.
resolve
(),
commit
:
()
=>
{},
},
{
...
response
,
status
:
httpStatusCodes
.
UNPROCESSABLE_ENTITY
,
errors
:
{
name
:
[
'
is reserved
'
]
},
},
)
.
then
(()
=>
{
shouldFlashAMessage
(
"
'uh oh' stage already exists
"
);
});
});
});
});
describe
(
'
initializeCycleAnalytics
'
,
()
=>
{
describe
(
'
initializeCycleAnalytics
'
,
()
=>
{
let
mockDispatch
;
let
mockDispatch
;
let
mockCommit
;
let
mockCommit
;
...
@@ -873,38 +741,6 @@ describe('Cycle analytics actions', () => {
...
@@ -873,38 +741,6 @@ describe('Cycle analytics actions', () => {
));
));
});
});
describe
(
'
receiveCreateStageSuccess
'
,
()
=>
{
const
response
=
{
data
:
{
title
:
'
COOL
'
,
},
};
it
(
'
will dispatch fetchGroupStagesAndEvents
'
,
()
=>
testAction
(
customStageActions
.
receiveCreateStageSuccess
,
response
,
state
,
[{
type
:
customStageTypes
.
RECEIVE_CREATE_STAGE_SUCCESS
}],
[{
type
:
'
fetchGroupStagesAndEvents
'
,
payload
:
null
},
{
type
:
'
clearSavingCustomStage
'
}],
));
describe
(
'
with an error
'
,
()
=>
{
it
(
'
will flash an error message
'
,
()
=>
customStageActions
.
receiveCreateStageSuccess
(
{
dispatch
:
()
=>
Promise
.
reject
(),
commit
:
()
=>
{},
},
response
,
)
.
then
(()
=>
{
shouldFlashAMessage
(
'
There was a problem refreshing the data, please try again
'
);
}));
});
});
describe
(
'
reorderStage
'
,
()
=>
{
describe
(
'
reorderStage
'
,
()
=>
{
const
stageId
=
'
cool-stage
'
;
const
stageId
=
'
cool-stage
'
;
const
payload
=
{
id
:
stageId
,
move_after_id
:
'
2
'
,
move_before_id
:
'
8
'
};
const
payload
=
{
id
:
stageId
,
move_after_id
:
'
2
'
,
move_before_id
:
'
8
'
};
...
...
ee/spec/frontend/analytics/cycle_analytics/store/modules/custom_stages/actions_spec.js
0 → 100644
View file @
817f6d4d
import
axios
from
'
axios
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
testAction
from
'
helpers/vuex_action_helper
'
;
import
*
as
actions
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/actions
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/mutation_types
'
;
import
createFlash
from
'
~/flash
'
;
import
httpStatusCodes
from
'
~/lib/utils/http_status
'
;
import
{
selectedGroup
,
endpoints
,
rawCustomStage
}
from
'
../../../mock_data
'
;
jest
.
mock
(
'
~/flash
'
);
describe
(
'
Custom stage actions
'
,
()
=>
{
let
state
;
let
mock
;
const
selectedStage
=
rawCustomStage
;
const
shouldFlashAMessage
=
(
msg
,
type
=
null
)
=>
{
const
args
=
type
?
[
msg
,
type
]
:
[
msg
];
expect
(
createFlash
).
toHaveBeenCalledWith
(...
args
);
};
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
});
afterEach
(()
=>
{
mock
.
restore
();
state
=
{
selectedGroup
:
null
};
});
describe
(
'
createStage
'
,
()
=>
{
describe
(
'
with valid data
'
,
()
=>
{
const
customStageData
=
{
startEventIdentifier
:
'
start_event
'
,
endEventIdentifier
:
'
end_event
'
,
name
:
'
cool-new-stage
'
,
};
beforeEach
(()
=>
{
state
=
{
...
state
,
selectedGroup
};
mock
.
onPost
(
endpoints
.
baseStagesEndpointstageData
).
reply
(
201
,
customStageData
);
});
it
(
`dispatches the 'receiveCreateStageSuccess' action`
,
()
=>
testAction
(
actions
.
createStage
,
customStageData
,
state
,
[],
[
{
type
:
'
clearFormErrors
'
},
{
type
:
'
setSavingCustomStage
'
},
{
type
:
'
receiveCreateStageSuccess
'
,
payload
:
{
data
:
customStageData
,
status
:
201
},
},
],
));
});
describe
(
'
with errors
'
,
()
=>
{
const
message
=
'
failed
'
;
const
errors
=
{
endEventIdentifier
:
[
'
Cant be blank
'
],
};
const
customStageData
=
{
startEventIdentifier
:
'
start_event
'
,
endEventIdentifier
:
''
,
name
:
'
cool-new-stage
'
,
};
beforeEach
(()
=>
{
state
=
{
...
state
,
selectedGroup
};
mock
.
onPost
(
endpoints
.
baseStagesEndpointstageData
)
.
reply
(
httpStatusCodes
.
UNPROCESSABLE_ENTITY
,
{
message
,
errors
,
});
});
it
(
`dispatches the 'receiveCreateStageError' action`
,
()
=>
testAction
(
actions
.
createStage
,
customStageData
,
state
,
[],
[
{
type
:
'
clearFormErrors
'
},
{
type
:
'
setSavingCustomStage
'
},
{
type
:
'
receiveCreateStageError
'
,
payload
:
{
data
:
customStageData
,
errors
,
message
,
status
:
httpStatusCodes
.
UNPROCESSABLE_ENTITY
,
},
},
],
));
});
});
describe
(
'
receiveCreateStageError
'
,
()
=>
{
const
response
=
{
data
:
{
name
:
'
uh oh
'
},
};
beforeEach
(()
=>
{});
it
(
'
will commit the RECEIVE_CREATE_STAGE_ERROR mutation
'
,
()
=>
testAction
(
actions
.
receiveCreateStageError
,
response
,
state
,
[{
type
:
types
.
RECEIVE_CREATE_STAGE_ERROR
}],
[{
type
:
'
setStageFormErrors
'
,
payload
:
{}
}],
));
it
(
'
will flash an error message
'
,
()
=>
{
return
actions
.
receiveCreateStageError
(
{
dispatch
:
()
=>
Promise
.
resolve
(),
commit
:
()
=>
{},
},
response
,
)
.
then
(()
=>
{
shouldFlashAMessage
(
'
There was a problem saving your custom stage, please try again
'
);
});
});
describe
(
'
with a stage name error
'
,
()
=>
{
it
(
'
will flash an error message
'
,
()
=>
{
return
actions
.
receiveCreateStageError
(
{
dispatch
:
()
=>
Promise
.
resolve
(),
commit
:
()
=>
{},
},
{
...
response
,
status
:
httpStatusCodes
.
UNPROCESSABLE_ENTITY
,
errors
:
{
name
:
[
'
is reserved
'
]
},
},
)
.
then
(()
=>
{
shouldFlashAMessage
(
"
'uh oh' stage already exists
"
);
});
});
});
});
describe
(
'
receiveCreateStageSuccess
'
,
()
=>
{
const
response
=
{
data
:
{
title
:
'
COOL
'
,
},
};
it
(
'
will dispatch fetchGroupStagesAndEvents
'
,
()
=>
testAction
(
actions
.
receiveCreateStageSuccess
,
response
,
state
,
[{
type
:
types
.
RECEIVE_CREATE_STAGE_SUCCESS
}],
[{
type
:
'
fetchGroupStagesAndEvents
'
,
payload
:
null
},
{
type
:
'
clearSavingCustomStage
'
}],
));
describe
(
'
with an error
'
,
()
=>
{
it
(
'
will flash an error message
'
,
()
=>
actions
.
receiveCreateStageSuccess
(
{
dispatch
:
()
=>
Promise
.
reject
(),
commit
:
()
=>
{},
},
response
,
)
.
then
(()
=>
{
shouldFlashAMessage
(
'
There was a problem refreshing the data, please try again
'
);
}));
});
});
describe
(
'
setStageFormErrors
'
,
()
=>
{
it
(
'
commits the "SET_STAGE_FORM_ERRORS" mutation
'
,
()
=>
{
return
testAction
(
actions
.
setStageFormErrors
,
[],
state
,
[{
type
:
types
.
SET_STAGE_FORM_ERRORS
,
payload
:
[]
}],
[],
);
});
});
describe
(
'
clearFormErrors
'
,
()
=>
{
it
(
'
commits the "CLEAR_FORM_ERRORS" mutation
'
,
()
=>
{
return
testAction
(
actions
.
clearFormErrors
,
[],
state
,
[{
type
:
types
.
CLEAR_FORM_ERRORS
}],
[],
);
});
});
describe
(
'
setStageEvents
'
,
()
=>
{
it
(
'
commits the "SET_STAGE_EVENTS" mutation
'
,
()
=>
{
return
testAction
(
actions
.
setStageEvents
,
[],
state
,
[{
type
:
types
.
SET_STAGE_EVENTS
,
payload
:
[]
}],
[],
);
});
});
describe
(
'
hideForm
'
,
()
=>
{
it
(
'
commits the "HIDE_FORM" mutation
'
,
()
=>
{
return
testAction
(
actions
.
hideForm
,
null
,
state
,
[{
type
:
types
.
HIDE_FORM
}],
[]);
});
});
describe
(
'
showCreateForm
'
,
()
=>
{
it
(
'
commits the "SHOW_CREATE_FORM" mutation
'
,
()
=>
{
return
testAction
(
actions
.
showCreateForm
,
null
,
state
,
[
{
type
:
types
.
SET_LOADING
},
{
type
:
types
.
SET_FORM_INITIAL_DATA
},
{
type
:
types
.
SHOW_CREATE_FORM
},
],
[],
);
});
});
describe
(
'
showEditForm
'
,
()
=>
{
it
(
'
commits the "SHOW_EDIT_FORM" mutation with initial data
'
,
()
=>
{
return
testAction
(
actions
.
showEditForm
,
selectedStage
,
state
,
[
{
type
:
types
.
SET_LOADING
},
{
type
:
types
.
SET_FORM_INITIAL_DATA
,
payload
:
rawCustomStage
},
{
type
:
types
.
SHOW_EDIT_FORM
},
],
[{
type
:
'
setSelectedStage
'
,
payload
:
rawCustomStage
},
{
type
:
'
clearSavingCustomStage
'
}],
);
});
});
});
ee/spec/frontend/analytics/cycle_analytics/store/modules/custom_stages/getters_spec.js
0 → 100644
View file @
817f6d4d
import
*
as
getters
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/getters
'
;
describe
(
'
Custom stages getters
'
,
()
=>
{
describe
.
each
`
state | result
${{
isCreatingCustomStage
:
true
,
isEditingCustomStage
:
true
}
} |
${
true
}
${{
isCreatingCustomStage
:
false
,
isEditingCustomStage
:
true
}
} |
${
true
}
${{
isCreatingCustomStage
:
true
,
isEditingCustomStage
:
false
}
} |
${
true
}
${{
isCreatingCustomStage
:
false
,
isEditingCustomStage
:
false
}
} |
${
false
}
`
(
'
customStageFormActive
'
,
({
state
,
result
})
=>
{
it
(
`with state
${
state
}
returns
${
result
}
`
,
()
=>
{
expect
(
getters
.
customStageFormActive
(
state
)).
toEqual
(
result
);
});
});
});
ee/spec/frontend/analytics/cycle_analytics/store/modules/custom_stages/mutations_spec.js
0 → 100644
View file @
817f6d4d
import
mutations
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/mutations
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/mutation_types
'
;
import
{
convertObjectPropsToCamelCase
}
from
'
~/lib/utils/common_utils
'
;
import
{
rawCustomStageEvents
,
camelCasedStageEvents
,
rawCustomStage
}
from
'
../../../mock_data
'
;
let
state
=
null
;
describe
(
'
Custom stage mutations
'
,
()
=>
{
beforeEach
(()
=>
{
state
=
{};
});
afterEach
(()
=>
{
state
=
null
;
});
it
.
each
`
mutation | stateKey | value
${
types
.
HIDE_FORM
}
|
${
'
isCreatingCustomStage
'
}
|
${
false
}
${
types
.
HIDE_FORM
}
|
${
'
isEditingCustomStage
'
}
|
${
false
}
${
types
.
HIDE_FORM
}
|
${
'
formErrors
'
}
|
${
null
}
${
types
.
HIDE_FORM
}
|
${
'
formInitialData
'
}
|
${
null
}
${
types
.
CLEAR_FORM_ERRORS
}
|
${
'
formErrors
'
}
|
${
null
}
${
types
.
SHOW_CREATE_FORM
}
|
${
'
isCreatingCustomStage
'
}
|
${
true
}
${
types
.
SHOW_CREATE_FORM
}
|
${
'
isEditingCustomStage
'
}
|
${
false
}
${
types
.
SHOW_CREATE_FORM
}
|
${
'
formErrors
'
}
|
${
null
}
${
types
.
SHOW_CREATE_FORM
}
|
${
'
formInitialData
'
}
|
${
null
}
${
types
.
SHOW_EDIT_FORM
}
|
${
'
isEditingCustomStage
'
}
|
${
true
}
${
types
.
SHOW_EDIT_FORM
}
|
${
'
isCreatingCustomStage
'
}
|
${
false
}
${
types
.
SHOW_EDIT_FORM
}
|
${
'
formErrors
'
}
|
${
null
}
${
types
.
RECEIVE_CREATE_STAGE_SUCCESS
}
|
${
'
formErrors
'
}
|
${
null
}
${
types
.
RECEIVE_CREATE_STAGE_SUCCESS
}
|
${
'
formInitialData
'
}
|
${
null
}
${
types
.
RECEIVE_CREATE_STAGE_ERROR
}
|
${
'
isSavingCustomStage
'
}
|
${
false
}
${
types
.
SET_SAVING_CUSTOM_STAGE
}
|
${
'
isSavingCustomStage
'
}
|
${
true
}
${
types
.
CLEAR_SAVING_CUSTOM_STAGE
}
|
${
'
isSavingCustomStage
'
}
|
${
false
}
${
types
.
SET_LOADING
}
|
${
'
isLoadingCustomStage
'
}
|
${
true
}
`
(
'
$mutation will set $stateKey=$value
'
,
({
mutation
,
stateKey
,
value
})
=>
{
mutations
[
mutation
](
state
);
expect
(
state
[
stateKey
]).
toEqual
(
value
);
});
describe
(
`
${
types
.
SET_STAGE_EVENTS
}
`
,
()
=>
{
it
(
'
will set formEvents
'
,
()
=>
{
state
=
{};
mutations
[
types
.
SET_STAGE_EVENTS
](
state
,
rawCustomStageEvents
);
expect
(
state
.
formEvents
).
toEqual
(
camelCasedStageEvents
);
});
});
describe
(
`
${
types
.
SET_STAGE_FORM_ERRORS
}
`
,
()
=>
{
const
mockFormError
=
{
start_identifier
:
[
'
Cant be blank
'
]
};
it
(
'
will set formErrors
'
,
()
=>
{
state
=
{};
mutations
[
types
.
SET_STAGE_FORM_ERRORS
](
state
,
mockFormError
);
expect
(
state
.
formErrors
).
toEqual
(
convertObjectPropsToCamelCase
(
mockFormError
));
});
});
describe
(
`
${
types
.
SET_FORM_INITIAL_DATA
}
`
,
()
=>
{
const
mockStage
=
{
endEventIdentifier
:
'
issue_first_added_to_board
'
,
endEventLabelId
:
null
,
id
:
18
,
name
:
'
Coolest beans stage
'
,
startEventIdentifier
:
'
issue_first_mentioned_in_commit
'
,
startEventLabelId
:
null
,
};
it
(
'
will set formInitialData
'
,
()
=>
{
state
=
{};
mutations
[
types
.
SET_FORM_INITIAL_DATA
](
state
,
rawCustomStage
);
expect
(
state
.
formInitialData
).
toEqual
(
mockStage
);
});
});
});
ee/spec/frontend/analytics/cycle_analytics/store/mutations_spec.js
View file @
817f6d4d
import
mutations
from
'
ee/analytics/cycle_analytics/store/mutations
'
;
import
mutations
from
'
ee/analytics/cycle_analytics/store/mutations
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/mutation_types
'
;
import
*
as
types
from
'
ee/analytics/cycle_analytics/store/mutation_types
'
;
import
customStageMutations
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/mutations
'
;
import
*
as
customStageTypes
from
'
ee/analytics/cycle_analytics/store/modules/custom_stages/mutation_types
'
;
import
{
convertObjectPropsToCamelCase
}
from
'
~/lib/utils/common_utils
'
;
import
{
import
{
issueStage
,
issueStage
,
...
@@ -13,9 +10,8 @@ import {
...
@@ -13,9 +10,8 @@ import {
totalStage
,
totalStage
,
startDate
,
startDate
,
endDate
,
endDate
,
customizableStagesAndEvents
,
selectedProjects
,
selectedProjects
,
rawCustomStage
,
customizableStagesAndEvents
,
}
from
'
../mock_data
'
;
}
from
'
../mock_data
'
;
let
state
=
null
;
let
state
=
null
;
...
@@ -70,65 +66,6 @@ describe('Cycle analytics mutations', () => {
...
@@ -70,65 +66,6 @@ describe('Cycle analytics mutations', () => {
},
},
);
);
describe
(
'
Custom stage mutations
'
,
()
=>
{
beforeEach
(()
=>
{
state
=
{};
});
afterEach
(()
=>
{
state
=
null
;
});
it
.
each
`
mutation | stateKey | value
${
customStageTypes
.
HIDE_FORM
}
|
${
'
isCreatingCustomStage
'
}
|
${
false
}
${
customStageTypes
.
HIDE_FORM
}
|
${
'
isEditingCustomStage
'
}
|
${
false
}
${
customStageTypes
.
HIDE_FORM
}
|
${
'
formErrors
'
}
|
${
null
}
${
customStageTypes
.
HIDE_FORM
}
|
${
'
formInitialData
'
}
|
${
null
}
${
customStageTypes
.
SHOW_CREATE_FORM
}
|
${
'
isCreatingCustomStage
'
}
|
${
true
}
${
customStageTypes
.
SHOW_CREATE_FORM
}
|
${
'
isEditingCustomStage
'
}
|
${
false
}
${
customStageTypes
.
SHOW_CREATE_FORM
}
|
${
'
formErrors
'
}
|
${
null
}
${
customStageTypes
.
SHOW_EDIT_FORM
}
|
${
'
isEditingCustomStage
'
}
|
${
true
}
${
customStageTypes
.
SHOW_EDIT_FORM
}
|
${
'
isCreatingCustomStage
'
}
|
${
false
}
${
customStageTypes
.
SHOW_EDIT_FORM
}
|
${
'
formErrors
'
}
|
${
null
}
${
customStageTypes
.
RECEIVE_CREATE_STAGE_ERROR
}
|
${
'
isSavingCustomStage
'
}
|
${
false
}
${
customStageTypes
.
SET_SAVING_CUSTOM_STAGE
}
|
${
'
isSavingCustomStage
'
}
|
${
true
}
${
customStageTypes
.
CLEAR_SAVING_CUSTOM_STAGE
}
|
${
'
isSavingCustomStage
'
}
|
${
false
}
`
(
'
$mutation will set $stateKey=$value
'
,
({
mutation
,
stateKey
,
value
})
=>
{
customStageMutations
[
mutation
](
state
);
expect
(
state
[
stateKey
]).
toEqual
(
value
);
});
describe
(
`
${
customStageTypes
.
SET_STAGE_FORM_ERRORS
}
`
,
()
=>
{
const
mockFormError
=
{
start_identifier
:
[
'
Cant be blank
'
]
};
it
(
'
will set formErrors
'
,
()
=>
{
state
=
{};
customStageMutations
[
customStageTypes
.
SET_STAGE_FORM_ERRORS
](
state
,
mockFormError
);
expect
(
state
.
formErrors
).
toEqual
(
convertObjectPropsToCamelCase
(
mockFormError
));
});
});
describe
(
`
${
customStageTypes
.
SET_FORM_INITIAL_DATA
}
`
,
()
=>
{
const
mockStage
=
{
id
:
18
,
name
:
'
Coolest beans stage
'
,
startEventIdentifier
:
'
issue_first_mentioned_in_commit
'
,
startEventLabelId
:
null
,
endEventIdentifier
:
'
issue_first_added_to_board
'
,
endEventLabelId
:
null
,
};
it
(
'
will set formInitialData
'
,
()
=>
{
state
=
{};
customStageMutations
[
customStageTypes
.
SET_FORM_INITIAL_DATA
](
state
,
rawCustomStage
);
expect
(
state
.
formInitialData
).
toEqual
(
mockStage
);
});
});
});
describe
(
`
${
types
.
RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS
}
`
,
()
=>
{
describe
(
`
${
types
.
RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS
}
`
,
()
=>
{
it
(
'
will set isLoading=false and errorCode=null
'
,
()
=>
{
it
(
'
will set isLoading=false and errorCode=null
'
,
()
=>
{
mutations
[
types
.
RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS
](
state
,
{
mutations
[
types
.
RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS
](
state
,
{
...
...
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