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
0219bbdd
Commit
0219bbdd
authored
Jun 02, 2021
by
Kushal Pandya
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'psi-cadence-edit' into 'master'
Add cadence edit page See merge request gitlab-org/gitlab!62587
parents
8ae2080e
d02d5775
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
325 additions
and
70 deletions
+325
-70
ee/app/assets/javascripts/iterations/components/iteration_cadence_form.vue
...ascripts/iterations/components/iteration_cadence_form.vue
+100
-24
ee/app/assets/javascripts/iterations/components/iteration_cadence_list_item.vue
...pts/iterations/components/iteration_cadence_list_item.vue
+20
-3
ee/app/assets/javascripts/iterations/components/iteration_cadences_list.vue
...scripts/iterations/components/iteration_cadences_list.vue
+10
-6
ee/app/assets/javascripts/iterations/index.js
ee/app/assets/javascripts/iterations/index.js
+1
-0
ee/app/assets/javascripts/iterations/queries/cadence_create.mutation.graphql
...cripts/iterations/queries/cadence_create.mutation.graphql
+10
-0
ee/app/assets/javascripts/iterations/queries/cadence_update.mutation.graphql
...cripts/iterations/queries/cadence_update.mutation.graphql
+10
-0
ee/app/assets/javascripts/iterations/queries/iteration_cadence.fragment.graphql
...pts/iterations/queries/iteration_cadence.fragment.graphql
+8
-0
ee/app/assets/javascripts/iterations/queries/iteration_cadence.query.graphql
...cripts/iterations/queries/iteration_cadence.query.graphql
+12
-0
ee/app/assets/javascripts/iterations/router.js
ee/app/assets/javascripts/iterations/router.js
+5
-0
ee/spec/frontend/iterations/components/iteration_cadence_form_spec.js
...tend/iterations/components/iteration_cadence_form_spec.js
+120
-36
ee/spec/frontend/iterations/components/iteration_cadence_list_item_spec.js
...iterations/components/iteration_cadence_list_item_spec.js
+15
-1
ee/spec/frontend/iterations/components/iteration_cadences_list_spec.js
...end/iterations/components/iteration_cadences_list_spec.js
+2
-0
locale/gitlab.pot
locale/gitlab.pot
+12
-0
No files found.
ee/app/assets/javascripts/iterations/components/iteration_cadence_form.vue
View file @
0219bbdd
...
@@ -9,8 +9,11 @@ import {
...
@@ -9,8 +9,11 @@ import {
GlFormInput
,
GlFormInput
,
GlFormSelect
,
GlFormSelect
,
}
from
'
@gitlab/ui
'
;
}
from
'
@gitlab/ui
'
;
import
{
convertToGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
createCadence
from
'
../queries/create_cadence.mutation.graphql
'
;
import
createCadence
from
'
../queries/cadence_create.mutation.graphql
'
;
import
updateCadence
from
'
../queries/cadence_update.mutation.graphql
'
;
import
readCadence
from
'
../queries/iteration_cadence.query.graphql
'
;
const
i18n
=
Object
.
freeze
({
const
i18n
=
Object
.
freeze
({
title
:
{
title
:
{
...
@@ -36,16 +39,22 @@ const i18n = Object.freeze({
...
@@ -36,16 +39,22 @@ const i18n = Object.freeze({
description
:
s__
(
'
Iterations|Number of future iterations you would like to have scheduled
'
),
description
:
s__
(
'
Iterations|Number of future iterations you would like to have scheduled
'
),
placeholder
:
s__
(
'
Iterations|Select number
'
),
placeholder
:
s__
(
'
Iterations|Select number
'
),
},
},
pageTitle
:
s__
(
'
Iterations|New iteration cadence
'
),
edit
:
{
create
:
s__
(
'
Iterations|Create cadence
'
),
title
:
s__
(
'
Iterations|Edit iteration cadence
'
),
save
:
s__
(
'
Iterations|Save cadence
'
),
},
new
:
{
title
:
s__
(
'
Iterations|New iteration cadence
'
),
save
:
s__
(
'
Iterations|Create cadence
'
),
},
cancel
:
__
(
'
Cancel
'
),
cancel
:
__
(
'
Cancel
'
),
requiredField
:
__
(
'
This field is required.
'
),
requiredField
:
__
(
'
This field is required.
'
),
});
});
export
default
{
export
default
{
availableDurations
:
[{
value
:
null
,
text
:
i18n
.
duration
.
placeholder
},
1
,
2
,
3
,
4
,
5
,
6
],
availableDurations
:
[{
value
:
0
,
text
:
i18n
.
duration
.
placeholder
},
1
,
2
,
3
,
4
,
5
,
6
],
availableFutureIterations
:
[
availableFutureIterations
:
[
{
value
:
null
,
text
:
i18n
.
futureIterations
.
placeholder
},
{
value
:
0
,
text
:
i18n
.
futureIterations
.
placeholder
},
2
,
2
,
4
,
4
,
6
,
6
,
...
@@ -67,15 +76,19 @@ export default {
...
@@ -67,15 +76,19 @@ export default {
inject
:
[
'
groupPath
'
,
'
cadencesListPath
'
],
inject
:
[
'
groupPath
'
,
'
cadencesListPath
'
],
data
()
{
data
()
{
return
{
return
{
cadences
:
[],
group
:
{
loading
:
false
,
iterationCadences
:
{
nodes
:
[],
},
},
loading
:
false
,
loading
:
false
,
errorMessage
:
''
,
errorMessage
:
''
,
title
:
''
,
title
:
''
,
automatic
:
true
,
automatic
:
true
,
startDate
:
null
,
startDate
:
null
,
durationInWeeks
:
null
,
durationInWeeks
:
0
,
rollOverIssues
:
false
,
iterationsInAdvance
:
0
,
iterationsInAdvance
:
null
,
validationState
:
{
validationState
:
{
title
:
null
,
title
:
null
,
startDate
:
null
,
startDate
:
null
,
...
@@ -86,29 +99,82 @@ export default {
...
@@ -86,29 +99,82 @@ export default {
};
};
},
},
computed
:
{
computed
:
{
loadingCadence
()
{
return
this
.
$apollo
.
queries
.
group
.
loading
;
},
cadenceId
()
{
return
this
.
$router
.
currentRoute
.
params
.
cadenceId
;
},
isEdit
()
{
return
Boolean
(
this
.
cadenceId
);
},
page
()
{
return
this
.
isEdit
?
'
edit
'
:
'
new
'
;
},
mutation
()
{
return
this
.
isEdit
?
updateCadence
:
createCadence
;
},
valid
()
{
valid
()
{
return
!
Object
.
values
(
this
.
validationState
).
includes
(
false
);
return
!
Object
.
values
(
this
.
validationState
).
includes
(
false
);
},
},
variables
()
{
variables
()
{
const
id
=
this
.
isEdit
?
convertToGraphQLId
(
'
Iterations::Cadence
'
,
this
.
cadenceId
)
:
undefined
;
const
groupPath
=
this
.
isEdit
?
undefined
:
this
.
groupPath
;
const
vars
=
{
const
vars
=
{
input
:
{
input
:
{
groupPath
:
this
.
groupPath
,
groupPath
,
id
,
title
:
this
.
title
,
title
:
this
.
title
,
automatic
:
this
.
automatic
,
automatic
:
this
.
automatic
,
startDate
:
this
.
startDate
,
startDate
:
this
.
startDate
,
durationInWeeks
:
this
.
durationInWeeks
,
durationInWeeks
:
this
.
durationInWeeks
,
active
:
true
,
active
:
true
,
iterationsInAdvance
:
this
.
iterationsInAdvance
,
},
},
};
};
if
(
this
.
automatic
)
{
vars
.
input
=
{
...
vars
.
input
,
iterationsInAdvance
:
this
.
iterationsInAdvance
,
};
}
return
vars
;
return
vars
;
},
},
},
},
apollo
:
{
group
:
{
skip
()
{
return
!
this
.
isEdit
;
},
query
:
readCadence
,
variables
()
{
return
{
fullPath
:
this
.
groupPath
,
id
:
this
.
cadenceId
,
};
},
result
({
data
:
{
group
,
errors
}
})
{
if
(
errors
?.
length
)
{
[
this
.
errorMessage
]
=
errors
;
return
;
}
const
cadence
=
group
?.
iterationCadences
?.
nodes
?.[
0
];
if
(
!
cadence
)
{
this
.
errorMessage
=
s__
(
"
Iterations|Couldn't find iteration cadence
"
);
return
;
}
this
.
title
=
cadence
.
title
;
this
.
automatic
=
cadence
.
automatic
;
this
.
startDate
=
cadence
.
startDate
;
this
.
durationInWeeks
=
cadence
.
durationInWeeks
;
this
.
iterationsInAdvance
=
cadence
.
iterationsInAdvance
;
},
error
(
error
)
{
this
.
errorMessage
=
error
;
},
},
},
methods
:
{
methods
:
{
validate
(
field
)
{
validate
(
field
)
{
this
.
validationState
[
field
]
=
Boolean
(
this
[
field
]);
this
.
validationState
[
field
]
=
Boolean
(
this
[
field
]);
...
@@ -131,6 +197,12 @@ export default {
...
@@ -131,6 +197,12 @@ export default {
this
.
validationState
.
durationInWeeks
=
null
;
this
.
validationState
.
durationInWeeks
=
null
;
this
.
validationState
.
iterationsInAdvance
=
null
;
this
.
validationState
.
iterationsInAdvance
=
null
;
},
},
updateAutomatic
(
value
)
{
this
.
clearValidation
();
if
(
!
value
)
{
this
.
iterationsInAdvance
=
0
;
}
},
save
()
{
save
()
{
this
.
validateAllFields
();
this
.
validateAllFields
();
...
@@ -147,18 +219,18 @@ export default {
...
@@ -147,18 +219,18 @@ export default {
createCadence
()
{
createCadence
()
{
return
this
.
$apollo
return
this
.
$apollo
.
mutate
({
.
mutate
({
mutation
:
createCadence
,
mutation
:
this
.
mutation
,
variables
:
this
.
variables
,
variables
:
this
.
variables
,
})
})
.
then
(({
data
,
errors
:
topLevelErrors
=
[]
})
=>
{
.
then
(({
data
,
errors
:
topLevelErrors
=
[]
}
=
{}
)
=>
{
if
(
topLevelErrors
.
length
>
0
)
{
if
(
topLevelErrors
.
length
>
0
)
{
this
.
errorMessage
=
topLevelErrors
[
0
].
message
;
this
.
errorMessage
=
topLevelErrors
[
0
].
message
;
return
;
return
;
}
}
const
{
errors
}
=
data
.
iterationCadenceCreate
;
const
{
errors
}
=
data
?.
result
||
{}
;
if
(
errors
.
length
>
0
)
{
if
(
errors
?
.
length
>
0
)
{
[
this
.
errorMessage
]
=
errors
;
[
this
.
errorMessage
]
=
errors
;
return
;
return
;
}
}
...
@@ -181,7 +253,7 @@ export default {
...
@@ -181,7 +253,7 @@ export default {
<article>
<article>
<div
class=
"gl-display-flex"
>
<div
class=
"gl-display-flex"
>
<h3
ref=
"pageTitle"
class=
"page-title"
>
<h3
ref=
"pageTitle"
class=
"page-title"
>
{{
i18n
.
pageT
itle
}}
{{
i18n
[
page
].
t
itle
}}
</h3>
</h3>
</div>
</div>
<gl-form>
<gl-form>
...
@@ -205,6 +277,7 @@ export default {
...
@@ -205,6 +277,7 @@ export default {
:placeholder=
"i18n.title.placeholder"
:placeholder=
"i18n.title.placeholder"
size=
"xl"
size=
"xl"
:state=
"validationState.title"
:state=
"validationState.title"
:disabled=
"loadingCadence"
@
blur=
"validate('title')"
@
blur=
"validate('title')"
/>
/>
</gl-form-group>
</gl-form-group>
...
@@ -218,7 +291,8 @@ export default {
...
@@ -218,7 +291,8 @@ export default {
<gl-form-checkbox
<gl-form-checkbox
id=
"cadence-automated-scheduling"
id=
"cadence-automated-scheduling"
v-model=
"automatic"
v-model=
"automatic"
@
change=
"clearValidation"
:disabled=
"loadingCadence"
@
change=
"updateAutomatic"
>
>
<span
class=
"gl-font-weight-bold"
>
{{
i18n
.
automatedScheduling
.
label
}}
</span>
<span
class=
"gl-font-weight-bold"
>
{{
i18n
.
automatedScheduling
.
label
}}
</span>
</gl-form-checkbox>
</gl-form-checkbox>
...
@@ -243,6 +317,7 @@ export default {
...
@@ -243,6 +317,7 @@ export default {
inputmode=
"none"
inputmode=
"none"
required
required
:state=
"validationState.startDate"
:state=
"validationState.startDate"
:disabled=
"loadingCadence"
data-qa-selector=
"cadence_start_date"
data-qa-selector=
"cadence_start_date"
@
blur=
"validate('startDate')"
@
blur=
"validate('startDate')"
/>
/>
...
@@ -265,6 +340,7 @@ export default {
...
@@ -265,6 +340,7 @@ export default {
class=
"gl-form-input-md"
class=
"gl-form-input-md"
required
required
data-qa-selector=
"iteration_cadence_name_field"
data-qa-selector=
"iteration_cadence_name_field"
:disabled=
"loadingCadence"
@
change=
"validate('durationInWeeks')"
@
change=
"validate('durationInWeeks')"
/>
/>
</gl-form-group>
</gl-form-group>
...
@@ -282,7 +358,7 @@ export default {
...
@@ -282,7 +358,7 @@ export default {
<gl-form-select
<gl-form-select
id=
"cadence-schedule-future-iterations"
id=
"cadence-schedule-future-iterations"
v-model.number=
"iterationsInAdvance"
v-model.number=
"iterationsInAdvance"
:disabled=
"!automatic"
:disabled=
"!automatic
|| loadingCadence
"
:options=
"$options.availableFutureIterations"
:options=
"$options.availableFutureIterations"
:required=
"automatic"
:required=
"automatic"
class=
"gl-form-input-md"
class=
"gl-form-input-md"
...
@@ -299,7 +375,7 @@ export default {
...
@@ -299,7 +375,7 @@ export default {
data-qa-selector=
"save_cadence_button"
data-qa-selector=
"save_cadence_button"
@
click=
"save"
@
click=
"save"
>
>
{{
i18n
.
creat
e
}}
{{
i18n
[
page
].
sav
e
}}
</gl-button>
</gl-button>
<gl-button
class=
"ml-auto"
data-testid=
"cancel-create-cadence"
@
click=
"cancel"
>
<gl-button
class=
"ml-auto"
data-testid=
"cancel-create-cadence"
@
click=
"cancel"
>
{{
i18n
.
cancel
}}
{{
i18n
.
cancel
}}
...
...
ee/app/assets/javascripts/iterations/components/iteration_cadence_list_item.vue
View file @
0219bbdd
...
@@ -3,6 +3,8 @@ import {
...
@@ -3,6 +3,8 @@ import {
GlAlert
,
GlAlert
,
GlButton
,
GlButton
,
GlCollapse
,
GlCollapse
,
GlDropdown
,
GlDropdownItem
,
GlIcon
,
GlIcon
,
GlInfiniteScroll
,
GlInfiniteScroll
,
GlSkeletonLoader
,
GlSkeletonLoader
,
...
@@ -24,6 +26,8 @@ export default {
...
@@ -24,6 +26,8 @@ export default {
GlAlert
,
GlAlert
,
GlButton
,
GlButton
,
GlCollapse
,
GlCollapse
,
GlDropdown
,
GlDropdownItem
,
GlIcon
,
GlIcon
,
GlInfiniteScroll
,
GlInfiniteScroll
,
GlSkeletonLoader
,
GlSkeletonLoader
,
...
@@ -42,7 +46,7 @@ export default {
...
@@ -42,7 +46,7 @@ export default {
},
},
},
},
},
},
inject
:
[
'
groupPath
'
],
inject
:
[
'
groupPath
'
,
'
canEditCadence
'
],
props
:
{
props
:
{
title
:
{
title
:
{
type
:
String
,
type
:
String
,
...
@@ -159,7 +163,7 @@ export default {
...
@@ -159,7 +163,7 @@ export default {
<div
class=
"gl-display-flex gl-align-items-center"
>
<div
class=
"gl-display-flex gl-align-items-center"
>
<gl-button
<gl-button
variant=
"link"
variant=
"link"
class=
"gl-font-weight-bold gl-text-body! gl-py-5! gl-px-3! gl-mr-auto"
class=
"gl-font-weight-bold gl-text-body! gl-py-5! gl-px-3! gl-mr-auto
gl-min-w-0
"
:aria-expanded=
"expanded"
:aria-expanded=
"expanded"
@
click=
"expanded = !expanded"
@
click=
"expanded = !expanded"
>
>
...
@@ -171,10 +175,23 @@ export default {
...
@@ -171,10 +175,23 @@ export default {
{{
title
}}
{{
title
}}
</gl-button>
</gl-button>
<span
v-if=
"durationInWeeks"
class=
"gl-mr-5"
>
<span
v-if=
"durationInWeeks"
class=
"gl-mr-5
gl-display-none gl-sm-display-inline-block
"
>
<gl-icon
name=
"clock"
class=
"gl-mr-3"
/>
<gl-icon
name=
"clock"
class=
"gl-mr-3"
/>
{{
n__
(
'
Every week
'
,
'
Every %d weeks
'
,
durationInWeeks
)
}}
</span
{{
n__
(
'
Every week
'
,
'
Every %d weeks
'
,
durationInWeeks
)
}}
</span
>
>
<gl-dropdown
v-if=
"canEditCadence"
icon=
"ellipsis_v"
category=
"tertiary"
right
lazy
text-sr-only
no-caret
>
<gl-dropdown-item
:to=
"editCadence"
>
{{
s__
(
'
Iterations|Edit cadence
'
)
}}
</gl-dropdown-item>
</gl-dropdown>
</div>
</div>
<gl-alert
v-if=
"error"
variant=
"danger"
:dismissible=
"true"
@
dismiss=
"error = ''"
>
<gl-alert
v-if=
"error"
variant=
"danger"
:dismissible=
"true"
@
dismiss=
"error = ''"
>
...
...
ee/app/assets/javascripts/iterations/components/iteration_cadences_list.vue
View file @
0219bbdd
...
@@ -32,10 +32,12 @@ export default {
...
@@ -32,10 +32,12 @@ export default {
data
()
{
data
()
{
return
{
return
{
group
:
{
group
:
{
iterationCadences
:
[],
iterationCadences
:
{
pageInfo
:
{
nodes
:
[],
hasNextPage
:
true
,
pageInfo
:
{
hasPreviousPage
:
false
,
hasNextPage
:
true
,
hasPreviousPage
:
false
,
},
},
},
},
},
pagination
:
{},
pagination
:
{},
...
@@ -104,11 +106,13 @@ export default {
...
@@ -104,11 +106,13 @@ export default {
<template
#title
>
<template
#title
>
{{
tab
}}
{{
tab
}}
</
template
>
</
template
>
<gl-loading-icon
v-if=
"loading"
class=
"gl-my-5"
size=
"lg"
/>
<gl-alert
v-
else-
if=
"error"
variant=
"danger"
@
dismiss=
"error = ''"
>
<gl-alert
v-if=
"error"
variant=
"danger"
@
dismiss=
"error = ''"
>
{{ error }}
{{ error }}
</gl-alert>
</gl-alert>
<gl-loading-icon
v-if=
"loading"
class=
"gl-my-5"
size=
"lg"
/>
<
template
v-else
>
<
template
v-else
>
<ul
v-if=
"cadences.length"
class=
"content-list"
>
<ul
v-if=
"cadences.length"
class=
"content-list"
>
<iteration-cadence-list-item
<iteration-cadence-list-item
...
...
ee/app/assets/javascripts/iterations/index.js
View file @
0219bbdd
...
@@ -114,6 +114,7 @@ export function initCadenceApp() {
...
@@ -114,6 +114,7 @@ export function initCadenceApp() {
router
,
router
,
apolloProvider
,
apolloProvider
,
provide
:
{
provide
:
{
fullPath
:
groupPath
,
groupPath
,
groupPath
,
cadencesListPath
,
cadencesListPath
,
canCreateCadence
:
parseBoolean
(
canCreateCadence
),
canCreateCadence
:
parseBoolean
(
canCreateCadence
),
...
...
ee/app/assets/javascripts/iterations/queries/c
reate_cadenc
e.mutation.graphql
→
ee/app/assets/javascripts/iterations/queries/c
adence_creat
e.mutation.graphql
View file @
0219bbdd
#import "./iteration_cadence.fragment.graphql"
mutation
createIterationCadence
(
$input
:
IterationCadenceCreateInput
!)
{
mutation
createIterationCadence
(
$input
:
IterationCadenceCreateInput
!)
{
iterationCadenceCreate
(
input
:
$input
)
{
result
:
iterationCadenceCreate
(
input
:
$input
)
{
iterationCadence
{
iterationCadence
{
id
...
IterationCadence
title
}
}
errors
errors
}
}
...
...
ee/app/assets/javascripts/iterations/queries/cadence_update.mutation.graphql
0 → 100644
View file @
0219bbdd
#import "./iteration_cadence.fragment.graphql"
mutation
updateIterationCadence
(
$input
:
IterationCadenceUpdateInput
!)
{
result
:
iterationCadenceUpdate
(
input
:
$input
)
{
iterationCadence
{
...
IterationCadence
}
errors
}
}
ee/app/assets/javascripts/iterations/queries/iteration_cadence.fragment.graphql
0 → 100644
View file @
0219bbdd
fragment
IterationCadence
on
IterationCadence
{
id
title
automatic
startDate
durationInWeeks
iterationsInAdvance
}
ee/app/assets/javascripts/iterations/queries/iteration_cadence.query.graphql
0 → 100644
View file @
0219bbdd
#import "./iteration_cadence.fragment.graphql"
# todo: should this use IterationsCadenceID! ?
query
IterationCadences
(
$fullPath
:
ID
!,
$id
:
ID
!)
{
group
(
fullPath
:
$fullPath
)
{
iterationCadences
(
id
:
$id
)
{
nodes
{
...
IterationCadence
}
}
}
}
ee/app/assets/javascripts/iterations/router.js
View file @
0219bbdd
...
@@ -12,6 +12,11 @@ const routes = [
...
@@ -12,6 +12,11 @@ const routes = [
path
:
'
/new
'
,
path
:
'
/new
'
,
component
:
IterationCadenceForm
,
component
:
IterationCadenceForm
,
},
},
{
name
:
'
edit
'
,
path
:
'
/:cadenceId/edit
'
,
component
:
IterationCadenceForm
,
},
{
{
name
:
'
index
'
,
name
:
'
index
'
,
path
:
'
/
'
,
path
:
'
/
'
,
...
...
ee/spec/frontend/iterations/components/iteration_cadence_form_spec.js
View file @
0219bbdd
import
{
GlFormCheckbox
,
GlFormGroup
}
from
'
@gitlab/ui
'
;
import
{
Gl
Alert
,
Gl
FormCheckbox
,
GlFormGroup
}
from
'
@gitlab/ui
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
Vue
from
'
vue
'
;
import
Vue
,
{
nextTick
}
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
IterationCadenceForm
from
'
ee/iterations/components/iteration_cadence_form.vue
'
;
import
IterationCadenceForm
from
'
ee/iterations/components/iteration_cadence_form.vue
'
;
import
createCadence
from
'
ee/iterations/queries/create_cadence.mutation.graphql
'
;
import
createCadence
from
'
ee/iterations/queries/cadence_create.mutation.graphql
'
;
import
readCadence
from
'
ee/iterations/queries/iteration_cadence.query.graphql
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
...
@@ -11,6 +13,9 @@ import waitForPromises from 'helpers/wait_for_promises';
...
@@ -11,6 +13,9 @@ import waitForPromises from 'helpers/wait_for_promises';
const
push
=
jest
.
fn
();
const
push
=
jest
.
fn
();
const
$router
=
{
const
$router
=
{
currentRoute
:
{
params
:
{},
},
push
,
push
,
};
};
...
@@ -25,24 +30,34 @@ describe('Iteration cadence form', () => {
...
@@ -25,24 +30,34 @@ describe('Iteration cadence form', () => {
const
groupPath
=
'
gitlab-org
'
;
const
groupPath
=
'
gitlab-org
'
;
const
id
=
72
;
const
id
=
72
;
const
iterationCadence
=
{
const
iterationCadence
=
{
id
:
`gid://gitlab/Iteration/
${
id
}
`
,
id
:
`gid://gitlab/Iteration
s::Cadence
/
${
id
}
`
,
title
:
'
An iteration
'
,
title
:
'
An iteration
'
,
description
:
'
The words
'
,
automatic
:
true
,
startDate
:
'
2020-06-28
'
,
startDate
:
'
2020-06-28
'
,
dueDate
:
'
2020-07-05
'
,
durationInWeeks
:
'
3
'
,
iterationsInAdvance
:
'
2
'
,
};
};
const
createMutationSuccess
=
{
const
createMutationSuccess
=
{
data
:
{
iterationCadenceCreate
:
{
iterationCadence
,
errors
:
[]
}
},
data
:
{
result
:
{
iterationCadence
,
errors
:
[]
}
},
};
};
const
createMutationFailure
=
{
const
createMutationFailure
=
{
data
:
{
data
:
{
iterationCadenceCreate
:
{
iterationCadence
,
errors
:
[
'
alas, your data is unchanged
'
]
},
result
:
{
iterationCadence
,
errors
:
[
'
alas, your data is unchanged
'
]
},
},
};
const
getCadenceSuccess
=
{
data
:
{
group
:
{
iterationCadences
:
{
nodes
:
[
iterationCadence
],
},
},
},
},
};
};
function
createComponent
({
resolverMock
}
=
{})
{
function
createComponent
({
query
=
createCadence
,
resolverMock
}
=
{})
{
const
apolloProvider
=
createMockApolloProvider
([[
createCadence
,
resolverMock
]]);
const
apolloProvider
=
createMockApolloProvider
([[
query
,
resolverMock
]]);
wrapper
=
extendedWrapper
(
wrapper
=
extendedWrapper
(
mount
(
IterationCadenceForm
,
{
mount
(
IterationCadenceForm
,
{
apolloProvider
,
apolloProvider
,
...
@@ -67,11 +82,30 @@ describe('Iteration cadence form', () => {
...
@@ -67,11 +82,30 @@ describe('Iteration cadence form', () => {
const
findDurationGroup
=
()
=>
wrapper
.
findAllComponents
(
GlFormGroup
).
at
(
3
);
const
findDurationGroup
=
()
=>
wrapper
.
findAllComponents
(
GlFormGroup
).
at
(
3
);
const
findFutureIterationsGroup
=
()
=>
wrapper
.
findAllComponents
(
GlFormGroup
).
at
(
4
);
const
findFutureIterationsGroup
=
()
=>
wrapper
.
findAllComponents
(
GlFormGroup
).
at
(
4
);
const
findError
=
()
=>
wrapper
.
findComponent
(
GlAlert
);
const
findTitle
=
()
=>
wrapper
.
find
(
'
#cadence-title
'
);
const
findTitle
=
()
=>
wrapper
.
find
(
'
#cadence-title
'
);
const
findStartDate
=
()
=>
wrapper
.
find
(
'
#cadence-start-date
'
);
const
findStartDate
=
()
=>
wrapper
.
find
(
'
#cadence-start-date
'
);
const
findFutureIterations
=
()
=>
wrapper
.
find
(
'
#cadence-schedule-future-iterations
'
);
const
findFutureIterations
=
()
=>
wrapper
.
find
(
'
#cadence-schedule-future-iterations
'
);
const
findDuration
=
()
=>
wrapper
.
find
(
'
#cadence-duration
'
);
const
findDuration
=
()
=>
wrapper
.
find
(
'
#cadence-duration
'
);
const
setTitle
=
(
value
)
=>
findTitle
().
vm
.
$emit
(
'
input
'
,
value
);
const
setStartDate
=
(
value
)
=>
findStartDate
().
vm
.
$emit
(
'
input
'
,
value
);
const
setFutureIterations
=
(
value
)
=>
findFutureIterations
().
vm
.
$emit
(
'
input
'
,
value
);
const
setDuration
=
(
value
)
=>
findDuration
().
vm
.
$emit
(
'
input
'
,
value
);
const
setAutomaticValue
=
(
value
)
=>
{
const
checkbox
=
findAutomatedSchedulingGroup
().
find
(
GlFormCheckbox
).
vm
;
checkbox
.
$emit
(
'
input
'
,
value
);
checkbox
.
$emit
(
'
change
'
,
value
);
};
const
findAllFields
=
()
=>
[
findTitle
(),
findStartDate
(),
findFutureIterations
(),
findDuration
(),
];
const
findSaveButton
=
()
=>
wrapper
.
findByTestId
(
'
save-cadence
'
);
const
findSaveButton
=
()
=>
wrapper
.
findByTestId
(
'
save-cadence
'
);
const
findCancelButton
=
()
=>
wrapper
.
findByTestId
(
'
cancel-create-cadence
'
);
const
findCancelButton
=
()
=>
wrapper
.
findByTestId
(
'
cancel-create-cadence
'
);
const
clickSave
=
()
=>
findSaveButton
().
vm
.
$emit
(
'
click
'
);
const
clickSave
=
()
=>
findSaveButton
().
vm
.
$emit
(
'
click
'
);
...
@@ -92,19 +126,20 @@ describe('Iteration cadence form', () => {
...
@@ -92,19 +126,20 @@ describe('Iteration cadence form', () => {
});
});
describe
(
'
save
'
,
()
=>
{
describe
(
'
save
'
,
()
=>
{
it
(
'
triggers mutation with form data
'
,
()
=>
{
const
title
=
'
Iteration 5
'
;
const
title
=
'
Iteration 5
'
;
const
startDate
=
'
2020-05-05
'
;
const
startDate
=
'
2020-05-05
'
;
const
durationInWeeks
=
2
;
const
durationInWeeks
=
2
;
const
iterationsInAdvance
=
6
;
const
iterationsInAdvance
=
6
;
findTitle
().
vm
.
$emit
(
'
input
'
,
title
);
it
(
'
triggers mutation with form data
'
,
()
=>
{
findStartDate
().
vm
.
$emit
(
'
input
'
,
startDate
);
setTitle
(
title
);
findDuration
().
vm
.
$emit
(
'
input
'
,
durationInWeeks
);
setStartDate
(
startDate
);
findFutureIterations
().
vm
.
$emit
(
'
input
'
,
iterationsInAdvance
);
setDuration
(
durationInWeeks
);
setFutureIterations
(
iterationsInAdvance
);
clickSave
();
clickSave
();
expect
(
findError
().
exists
()).
toBe
(
false
);
expect
(
resolverMock
).
toHaveBeenCalledWith
({
expect
(
resolverMock
).
toHaveBeenCalledWith
({
input
:
{
input
:
{
groupPath
,
groupPath
,
...
@@ -119,15 +154,10 @@ describe('Iteration cadence form', () => {
...
@@ -119,15 +154,10 @@ describe('Iteration cadence form', () => {
});
});
it
(
'
redirects to Iteration page on success
'
,
async
()
=>
{
it
(
'
redirects to Iteration page on success
'
,
async
()
=>
{
const
title
=
'
Iteration 5
'
;
setTitle
(
title
);
const
startDate
=
'
2020-05-05
'
;
setStartDate
(
startDate
);
const
durationInWeeks
=
2
;
setDuration
(
durationInWeeks
);
const
iterationsInAdvance
=
6
;
setFutureIterations
(
iterationsInAdvance
);
findTitle
().
vm
.
$emit
(
'
input
'
,
title
);
findStartDate
().
vm
.
$emit
(
'
input
'
,
startDate
);
findDuration
().
vm
.
$emit
(
'
input
'
,
durationInWeeks
);
findFutureIterations
().
vm
.
$emit
(
'
input
'
,
iterationsInAdvance
);
clickSave
();
clickSave
();
...
@@ -159,22 +189,28 @@ describe('Iteration cadence form', () => {
...
@@ -159,22 +189,28 @@ describe('Iteration cadence form', () => {
});
});
describe
(
'
automated scheduling disabled
'
,
()
=>
{
describe
(
'
automated scheduling disabled
'
,
()
=>
{
beforeEach
(()
=>
{
it
(
'
disables future iterations
'
,
async
()
=>
{
findAutomatedSchedulingGroup
().
find
(
GlFormCheckbox
).
vm
.
$emit
(
'
input
'
,
false
);
setAutomaticValue
(
false
);
});
await
nextTick
();
it
(
'
disables future iterations
'
,
()
=>
{
expect
(
findFutureIterations
().
attributes
(
'
disabled
'
)).
toBe
(
'
disabled
'
);
expect
(
findFutureIterations
().
attributes
(
'
disabled
'
)).
toBe
(
'
disabled
'
);
});
});
it
(
'
does not require future iterations
'
,
()
=>
{
it
(
'
sets future iterations to 0
'
,
async
()
=>
{
const
title
=
'
Iteration 5
'
;
const
title
=
'
Iteration 5
'
;
const
startDate
=
'
2020-05-05
'
;
const
startDate
=
'
2020-05-05
'
;
const
durationInWeeks
=
2
;
const
durationInWeeks
=
2
;
findTitle
().
vm
.
$emit
(
'
input
'
,
title
);
setFutureIterations
(
10
);
findStartDate
().
vm
.
$emit
(
'
input
'
,
startDate
);
findDuration
().
vm
.
$emit
(
'
input
'
,
durationInWeeks
);
setAutomaticValue
(
false
);
await
nextTick
();
setTitle
(
title
);
setStartDate
(
startDate
);
setDuration
(
durationInWeeks
);
clickSave
();
clickSave
();
...
@@ -185,10 +221,58 @@ describe('Iteration cadence form', () => {
...
@@ -185,10 +221,58 @@ describe('Iteration cadence form', () => {
automatic
:
false
,
automatic
:
false
,
startDate
,
startDate
,
durationInWeeks
,
durationInWeeks
,
iterationsInAdvance
:
0
,
active
:
true
,
active
:
true
,
},
},
});
});
});
});
});
});
});
});
describe
(
'
Edit cadence
'
,
()
=>
{
const
query
=
readCadence
;
const
resolverMock
=
jest
.
fn
().
mockResolvedValue
(
getCadenceSuccess
);
beforeEach
(()
=>
{
$router
.
currentRoute
.
params
.
cadenceId
=
id
;
});
afterEach
(()
=>
{
delete
$router
.
currentRoute
.
params
.
cadenceId
;
});
it
(
'
shows correct title and button text
'
,
()
=>
{
createComponent
({
query
,
resolverMock
});
expect
(
wrapper
.
text
()).
toContain
(
wrapper
.
vm
.
i18n
.
edit
.
title
);
expect
(
wrapper
.
text
()).
toContain
(
wrapper
.
vm
.
i18n
.
edit
.
save
);
});
it
(
'
disables fields while loading
'
,
async
()
=>
{
createComponent
({
query
,
resolverMock
});
findAllFields
().
forEach
(({
element
})
=>
{
expect
(
element
).
toBeDisabled
();
});
await
waitForPromises
();
findAllFields
().
forEach
(({
element
})
=>
{
expect
(
element
).
not
.
toBeDisabled
();
});
});
it
(
'
fills fields with existing cadence info after loading
'
,
async
()
=>
{
createComponent
({
query
,
resolverMock
});
await
waitForPromises
();
await
nextTick
();
expect
(
findTitle
().
element
.
value
).
toBe
(
iterationCadence
.
title
);
expect
(
findStartDate
().
element
.
value
).
toBe
(
iterationCadence
.
startDate
);
expect
(
findFutureIterations
().
element
.
value
).
toBe
(
iterationCadence
.
iterationsInAdvance
);
expect
(
findDuration
().
element
.
value
).
toBe
(
iterationCadence
.
durationInWeeks
);
});
});
});
});
ee/spec/frontend/iterations/components/iteration_cadence_list_item_spec.js
View file @
0219bbdd
import
{
GlInfiniteScroll
,
GlSkeletonLoader
}
from
'
@gitlab/ui
'
;
import
{
Gl
Dropdown
,
Gl
InfiniteScroll
,
GlSkeletonLoader
}
from
'
@gitlab/ui
'
;
import
{
createLocalVue
,
RouterLinkStub
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
,
RouterLinkStub
}
from
'
@vue/test-utils
'
;
import
{
nextTick
}
from
'
vue
'
;
import
{
nextTick
}
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
VueApollo
from
'
vue-apollo
'
;
...
@@ -82,6 +82,7 @@ describe('Iteration cadence list item', () => {
...
@@ -82,6 +82,7 @@ describe('Iteration cadence list item', () => {
function
createComponent
({
function
createComponent
({
props
=
{},
props
=
{},
canCreateCadence
,
canCreateCadence
,
canEditCadence
,
resolverMock
=
jest
.
fn
().
mockResolvedValue
(
querySuccessResponse
),
resolverMock
=
jest
.
fn
().
mockResolvedValue
(
querySuccessResponse
),
}
=
{})
{
}
=
{})
{
apolloProvider
=
createMockApolloProvider
([[
iterationsInCadenceQuery
,
resolverMock
]]);
apolloProvider
=
createMockApolloProvider
([[
iterationsInCadenceQuery
,
resolverMock
]]);
...
@@ -98,6 +99,7 @@ describe('Iteration cadence list item', () => {
...
@@ -98,6 +99,7 @@ describe('Iteration cadence list item', () => {
provide
:
{
provide
:
{
groupPath
,
groupPath
,
canCreateCadence
,
canCreateCadence
,
canEditCadence
,
},
},
propsData
:
{
propsData
:
{
title
:
cadence
.
title
,
title
:
cadence
.
title
,
...
@@ -185,4 +187,16 @@ describe('Iteration cadence list item', () => {
...
@@ -185,4 +187,16 @@ describe('Iteration cadence list item', () => {
}),
}),
);
);
});
});
it
(
'
hides dropdown when canEditCadence is false
'
,
async
()
=>
{
await
createComponent
({
canEditCadence
:
false
});
expect
(
wrapper
.
find
(
GlDropdown
).
exists
()).
toBe
(
false
);
});
it
(
'
shows dropdown when canEditCadence is true
'
,
async
()
=>
{
await
createComponent
({
canEditCadence
:
true
});
expect
(
wrapper
.
find
(
GlDropdown
).
exists
()).
toBe
(
true
);
});
});
});
ee/spec/frontend/iterations/components/iteration_cadences_list_spec.js
View file @
0219bbdd
...
@@ -82,6 +82,7 @@ describe('Iteration cadences list', () => {
...
@@ -82,6 +82,7 @@ describe('Iteration cadences list', () => {
function
createComponent
({
function
createComponent
({
canCreateCadence
,
canCreateCadence
,
canEditCadence
,
resolverMock
=
jest
.
fn
().
mockResolvedValue
(
querySuccessResponse
),
resolverMock
=
jest
.
fn
().
mockResolvedValue
(
querySuccessResponse
),
}
=
{})
{
}
=
{})
{
apolloProvider
=
createMockApolloProvider
([[
cadencesListQuery
,
resolverMock
]]);
apolloProvider
=
createMockApolloProvider
([[
cadencesListQuery
,
resolverMock
]]);
...
@@ -96,6 +97,7 @@ describe('Iteration cadences list', () => {
...
@@ -96,6 +97,7 @@ describe('Iteration cadences list', () => {
groupPath
,
groupPath
,
cadencesListPath
,
cadencesListPath
,
canCreateCadence
,
canCreateCadence
,
canEditCadence
,
},
},
});
});
...
...
locale/gitlab.pot
View file @
0219bbdd
...
@@ -18556,12 +18556,21 @@ msgstr ""
...
@@ -18556,12 +18556,21 @@ msgstr ""
msgid "Iterations|Cadence name"
msgid "Iterations|Cadence name"
msgstr ""
msgstr ""
msgid "Iterations|Couldn't find iteration cadence"
msgstr ""
msgid "Iterations|Create cadence"
msgid "Iterations|Create cadence"
msgstr ""
msgstr ""
msgid "Iterations|Duration"
msgid "Iterations|Duration"
msgstr ""
msgstr ""
msgid "Iterations|Edit cadence"
msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
msgid "Iterations|Error loading iteration cadences."
msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgstr ""
...
@@ -18583,6 +18592,9 @@ msgstr ""
...
@@ -18583,6 +18592,9 @@ msgstr ""
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr ""
msgstr ""
msgid "Iterations|Save cadence"
msgstr ""
msgid "Iterations|Select duration"
msgid "Iterations|Select duration"
msgstr ""
msgstr ""
...
...
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