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
d02d5775
Commit
d02d5775
authored
Jun 02, 2021
by
Simon Knox
Committed by
Kushal Pandya
Jun 02, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add cadence edit page
parent
4ca65e16
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 @
d02d5775
...
@@ -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 @
d02d5775
...
@@ -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 @
d02d5775
...
@@ -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 @
d02d5775
...
@@ -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 @
d02d5775
#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 @
d02d5775
#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 @
d02d5775
fragment
IterationCadence
on
IterationCadence
{
id
title
automatic
startDate
durationInWeeks
iterationsInAdvance
}
ee/app/assets/javascripts/iterations/queries/iteration_cadence.query.graphql
0 → 100644
View file @
d02d5775
#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 @
d02d5775
...
@@ -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 @
d02d5775
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 @
d02d5775
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 @
d02d5775
...
@@ -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 @
d02d5775
...
@@ -18550,12 +18550,21 @@ msgstr ""
...
@@ -18550,12 +18550,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 ""
...
@@ -18577,6 +18586,9 @@ msgstr ""
...
@@ -18577,6 +18586,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