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
4a8b8929
Commit
4a8b8929
authored
Apr 10, 2020
by
Kushal Pandya
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'health-status-dropdown' into 'master'
Use dropdown to change health status See merge request gitlab-org/gitlab!28547
parents
3f474171
24198491
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
225 additions
and
219 deletions
+225
-219
app/assets/stylesheets/framework/sidebar.scss
app/assets/stylesheets/framework/sidebar.scss
+12
-0
doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png
...roject/issues/img/issue_health_status_dropdown_v12_10.png
+0
-0
doc/user/project/issues/index.md
doc/user/project/issues/index.md
+1
-1
ee/app/assets/javascripts/sidebar/components/status/sidebar_status.vue
.../javascripts/sidebar/components/status/sidebar_status.vue
+2
-2
ee/app/assets/javascripts/sidebar/components/status/status.vue
...p/assets/javascripts/sidebar/components/status/status.vue
+93
-62
ee/app/assets/javascripts/sidebar/constants.js
ee/app/assets/javascripts/sidebar/constants.js
+0
-6
ee/changelogs/unreleased/health-status-dropdown.yml
ee/changelogs/unreleased/health-status-dropdown.yml
+5
-0
ee/spec/frontend/sidebar/components/status/sidebar_status_spec.js
...frontend/sidebar/components/status/sidebar_status_spec.js
+31
-62
ee/spec/frontend/sidebar/components/status/status_spec.js
ee/spec/frontend/sidebar/components/status/status_spec.js
+69
-77
locale/gitlab.pot
locale/gitlab.pot
+12
-9
No files found.
app/assets/stylesheets/framework/sidebar.scss
View file @
4a8b8929
...
...
@@ -210,3 +210,15 @@
}
}
}
.health-status
{
.dropdown-body
{
.health-divider
{
border-top-color
:
$gray-200
;
}
.dropdown-item
:not
(
.health-dropdown-item
)
{
padding
:
0
;
}
}
}
doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png
0 → 100644
View file @
4a8b8929
43.7 KB
doc/user/project/issues/index.md
View file @
4a8b8929
...
...
@@ -177,7 +177,7 @@ that's progressing as planned or needs attention to keep on schedule:
-
**Needs attention**
(amber)
-
**At risk**
(red)
![
"On track" health status on an issue
](
img/issue_health_status_v12_10.png
)
![
"On track" health status on an issue
](
img/issue_health_status_
dropdown_
v12_10.png
)
You can then see issue statuses on the
[
Epic tree
](
../../group/epics/index.md#issue-health-status-in-epic-tree-ultimate
)
.
...
...
ee/app/assets/javascripts/sidebar/components/status/sidebar_status.vue
View file @
4a8b8929
...
...
@@ -17,7 +17,7 @@ export default {
},
},
methods
:
{
handle
FormSubmission
(
status
)
{
handle
DropdownClick
(
status
)
{
this
.
mediator
.
updateStatus
(
status
).
catch
(()
=>
{
Flash
(
__
(
'
Error occurred while updating the issue status
'
));
});
...
...
@@ -31,6 +31,6 @@ export default {
:is-editable=
"mediator.store.editable"
:is-fetching=
"mediator.store.isFetching.status"
:status=
"mediator.store.status"
@
on
StatusChange=
"handleFormSubmission
"
@
on
DropdownClick=
"handleDropdownClick
"
/>
</
template
>
ee/app/assets/javascripts/sidebar/components/status/status.vue
View file @
4a8b8929
<
script
>
import
Tracking
from
'
~/tracking
'
;
import
{
GlDeprecatedButton
,
GlFormGroup
,
GlFormRadioGroup
,
GlIcon
,
GlNewButton
,
GlLoadingIcon
,
GlTooltip
,
GlDropdownItem
,
GlDropdown
,
GlDropdownDivider
,
}
from
'
@gitlab/ui
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
healthStatus
ColorMap
,
healthStatus
TextMap
}
from
'
../../constants
'
;
import
{
healthStatusTextMap
}
from
'
../../constants
'
;
export
default
{
components
:
{
GlDeprecatedButton
,
GlIcon
,
GlNewButton
,
GlLoadingIcon
,
GlFormGroup
,
GlFormRadioGroup
,
GlTooltip
,
GlDropdown
,
GlDropdownItem
,
GlDropdownDivider
,
},
mixins
:
[
Tracking
.
mixin
()],
props
:
{
isEditable
:
{
type
:
Boolean
,
...
...
@@ -38,11 +42,11 @@ export default {
},
data
()
{
return
{
is
Form
Showing
:
false
,
is
Dropdown
Showing
:
false
,
selectedStatus
:
this
.
status
,
statusOptions
:
Object
.
keys
(
healthStatusTextMap
).
map
(
key
=>
({
value
:
key
,
text
:
healthStatusTextMap
[
key
],
key
,
value
:
healthStatusTextMap
[
key
],
})),
};
},
...
...
@@ -53,11 +57,11 @@ export default {
statusText
()
{
return
this
.
status
?
healthStatusTextMap
[
this
.
status
]
:
s__
(
'
Sidebar|None
'
);
},
statusColor
()
{
return
healthStatusColorMap
[
this
.
status
]
;
dropdownText
()
{
return
this
.
status
?
healthStatusTextMap
[
this
.
status
]
:
s__
(
'
Select health status
'
)
;
},
tooltipText
()
{
let
tooltipText
=
s__
(
'
Sidebar|
S
tatus
'
);
let
tooltipText
=
s__
(
'
Sidebar|
Health s
tatus
'
);
if
(
this
.
status
)
{
tooltipText
+=
`:
${
this
.
statusText
}
`
;
...
...
@@ -72,19 +76,33 @@ export default {
},
},
methods
:
{
handleFormSubmission
()
{
this
.
$emit
(
'
onStatusChange
'
,
this
.
selectedStatus
);
this
.
hideForm
();
handleDropdownClick
(
status
)
{
this
.
selectedStatus
=
status
;
this
.
$emit
(
'
onDropdownClick
'
,
status
);
this
.
track
(
'
change_health_status
'
,
{
property
:
status
});
this
.
hideDropdown
();
},
hideForm
()
{
this
.
isFormShowing
=
false
;
this
.
$refs
.
editButton
.
focus
();
hideDropdown
()
{
this
.
isDropdownShowing
=
false
;
},
toggleFormDropdown
()
{
this
.
isFormShowing
=
!
this
.
isFormShowing
;
this
.
isDropdownShowing
=
!
this
.
isDropdownShowing
;
/**
* We need to programmatically open the dropdown to make the
* outside click on document close the dropdown.
*/
const
{
dropdown
}
=
this
.
$refs
.
dropdown
.
$refs
;
if
(
dropdown
&&
this
.
isDropdownShowing
)
{
dropdown
.
show
();
}
},
removeStatus
()
{
this
.
$emit
(
'
onStatusChange
'
,
null
);
this
.
handleDropdownClick
(
null
);
},
isSelected
(
status
)
{
return
this
.
status
===
status
;
},
},
};
...
...
@@ -104,62 +122,75 @@ export default {
<div
class=
"hide-collapsed"
>
<p
class=
"title d-flex justify-content-between"
>
{{
s__
(
'
Sidebar|
S
tatus
'
)
}}
{{
s__
(
'
Sidebar|
Health s
tatus
'
)
}}
<a
v-if=
"isEditable"
ref=
"editButton"
class=
"btn-link"
href=
"#"
@
click=
"toggleFormDropdown"
@
keydown.esc=
"hide
Form
"
@
keydown.esc=
"hide
Dropdown
"
>
{{
__
(
'
Edit
'
)
}}
</a>
</p>
<div
v-if=
"isFormShowing"
class=
"dropdown show"
>
<form
class=
"dropdown-menu p-3"
@
submit.prevent=
"handleFormSubmission"
>
<p>
{{
__
(
'
Choose which status most accurately reflects the current state of this issue:
'
)
}}
</p>
<gl-form-group>
<gl-form-radio-group
v-model=
"selectedStatus"
:checked=
"selectedStatus"
:options=
"statusOptions"
stacked
@
keydown.esc.native=
"hideForm"
<div
class=
"dropdown dropdown-menu-selectable"
:class=
"
{ show: isDropdownShowing, 'd-none': !isDropdownShowing }"
>
<gl-dropdown
ref=
"dropdown"
class=
"w-100"
:text=
"dropdownText"
@
keydown.esc.native=
"hideDropdown"
@
hide=
"hideDropdown"
>
<div
class=
"dropdown-title"
>
<span
class=
"health-title"
>
{{
s__
(
'
Sidebar|Assign health status
'
)
}}
</span>
<gl-new-button
:aria-label=
"__('Close')"
variant=
"link"
class=
"dropdown-title-button dropdown-menu-close"
icon=
"close"
@
click=
"hideDropdown"
/>
</gl-form-group>
<gl-form-group
class=
"mb-0"
>
<gl-deprecated-button
type=
"button"
class=
"append-right-10"
@
click=
"hideForm"
>
{{
__
(
'
Cancel
'
)
}}
</gl-deprecated-button>
<gl-deprecated-button
type=
"submit"
variant=
"success"
>
{{
__
(
'
Save
'
)
}}
</gl-deprecated-button>
</gl-form-group>
</form>
</div>
<div
class=
"dropdown-content dropdown-body"
>
<gl-dropdown-item
@
click=
"handleDropdownClick(null)"
>
<gl-new-button
variant=
"link"
class=
"dropdown-item health-dropdown-item"
:class=
"
{ 'is-active': isSelected(null) }"
>
{{
s__
(
'
Sidebar|No status
'
)
}}
</gl-new-button>
</gl-dropdown-item>
<gl-dropdown-divider
class=
"divider health-divider"
/>
<gl-dropdown-item
v-for=
"option in statusOptions"
:key=
"option.key"
@
click=
"handleDropdownClick(option.key)"
>
<gl-new-button
variant=
"link"
class=
"dropdown-item health-dropdown-item"
:class=
"
{ 'is-active': isSelected(option.key) }"
>
{{
option
.
value
}}
</gl-new-button>
</gl-dropdown-item>
</div>
</gl-dropdown>
</div>
<gl-loading-icon
v-if=
"isFetching"
:inline=
"true"
/>
<p
v-else
class=
"value d-flex align-items-center m-0"
:class=
"
{ 'no-value': !status }">
<gl-icon
v-if=
"status"
name=
"severity-low"
:size=
"14"
class=
"align-bottom append-right-10"
:class=
"statusColor"
/>
{{
statusText
}}
<template
v-if=
"canRemoveStatus"
>
<span
class=
"text-secondary mx-1"
aria-hidden=
"true"
>
-
</span>
<gl-deprecated-button
variant=
"link"
class=
"text-secondary"
@
click=
"removeStatus"
>
{{
__
(
'
remove status
'
)
}}
</gl-deprecated-button>
</
template
>
<p
v-else-if=
"!isDropdownShowing"
class=
"value m-0"
:class=
"
{ 'no-value': !status }">
<span
v-if=
"status"
class=
"text-plain bold"
>
{{
statusText
}}
</span>
<span
v-else
>
{{
__
(
'
None
'
)
}}
</span>
</p>
</div>
</div>
...
...
ee/app/assets/javascripts/sidebar/constants.js
View file @
4a8b8929
...
...
@@ -6,12 +6,6 @@ export const healthStatus = {
AT_RISK
:
'
atRisk
'
,
};
export
const
healthStatusColorMap
=
{
[
healthStatus
.
ON_TRACK
]:
'
text-success
'
,
[
healthStatus
.
NEEDS_ATTENTION
]:
'
text-warning
'
,
[
healthStatus
.
AT_RISK
]:
'
text-danger
'
,
};
export
const
healthStatusTextMap
=
{
[
healthStatus
.
ON_TRACK
]:
__
(
'
On track
'
),
[
healthStatus
.
NEEDS_ATTENTION
]:
__
(
'
Needs attention
'
),
...
...
ee/changelogs/unreleased/health-status-dropdown.yml
0 → 100644
View file @
4a8b8929
---
title
:
Use dropdown to change health status
merge_request
:
28547
author
:
type
:
changed
ee/spec/frontend/sidebar/components/status/sidebar_status_spec.js
View file @
4a8b8929
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
Vue
from
'
vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
SidebarStatus
from
'
ee/sidebar/components/status/sidebar_status.vue
'
;
import
Status
from
'
ee/sidebar/components/status/status.vue
'
;
const
getStatusText
=
wrapper
=>
wrapper
.
find
(
'
.value
'
).
text
();
describe
(
'
SidebarStatus
'
,
()
=>
{
let
wrapper
;
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
Status child component
'
,
()
=>
{
let
handleFormSubmissionMock
;
let
handleDropdownClickMock
;
beforeEach
(()
=>
{
const
mediator
=
{
...
...
@@ -26,61 +16,40 @@ describe('SidebarStatus', () => {
},
};
handleFormSubmission
Mock
=
jest
.
fn
();
handleDropdownClick
Mock
=
jest
.
fn
();
wrapper
=
shallowMount
(
SidebarStatus
,
{
propsData
:
{
mediator
,
},
methods
:
{
handleFormSubmission
:
handleFormSubmission
Mock
,
handleDropdownClick
:
handleDropdownClick
Mock
,
},
});
});
it
(
'
renders Status component
'
,
()
=>
{
expect
(
wrapper
.
contains
(
Status
)).
toBe
(
true
);
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
calls handleFormSubmission when receiving an onStatusChange event from Status
component
'
,
()
=>
{
wrapper
.
find
(
Status
).
vm
.
$emit
(
'
onStatusChange
'
,
'
onTrack
'
);
describe
(
'
Status child
component
'
,
()
=>
{
beforeEach
(()
=>
{}
);
expect
(
handleFormSubmissionMock
).
toHaveBeenCalledWith
(
'
onTrack
'
);
}
);
it
(
'
renders Status component
'
,
()
=>
{
expect
(
wrapper
.
contains
(
Status
)).
toBe
(
true
);
});
it
(
'
removes status when user clicks on "remove status"
'
,
()
=>
{
const
mediator
=
{
store
:
{
editable
:
true
,
isFetching
:
{
status
:
false
,
},
status
:
'
onTrack
'
,
},
updateStatus
(
status
)
{
this
.
store
.
status
=
status
;
wrapper
.
setProps
({
mediator
:
{
...
this
,
},
});
return
Promise
.
resolve
();
},
};
it
(
'
calls handleFormSubmission when receiving an onDropdownClick event from Status component
'
,
()
=>
{
wrapper
.
find
(
Status
).
vm
.
$emit
(
'
onDropdownClick
'
,
'
onTrack
'
);
wrapper
=
mount
(
SidebarStatus
,
{
propsData
:
{
mediator
,
},
expect
(
handleDropdownClickMock
).
toHaveBeenCalledWith
(
'
onTrack
'
);
});
});
expect
(
getStatusText
(
wrapper
)).
toContain
(
'
On track
'
);
wrapper
.
find
(
'
button.btn-link
'
).
trigger
(
'
click
'
);
it
(
'
calls handleFormSubmission when receiving an onFormSubmit event from Status component
'
,
()
=>
{
wrapper
.
find
(
Status
).
vm
.
$emit
(
'
onDropdownClick
'
,
'
onTrack
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
expect
(
getStatusText
(
wrapper
)).
toBe
(
'
None
'
);
});
expect
(
handleDropdownClickMock
).
toHaveBeenCalledWith
(
'
onTrack
'
);
});
});
ee/spec/frontend/sidebar/components/status/status_spec.js
View file @
4a8b8929
import
{
GlD
eprecatedButton
,
GlFormRadioGroup
,
GlLoadingIcon
,
GlTooltip
}
from
'
@gitlab/ui
'
;
import
{
GlD
ropdown
,
GlDropdownItem
,
GlLoadingIcon
,
GlTooltip
}
from
'
@gitlab/ui
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
Vue
from
'
vue
'
;
import
Status
from
'
ee/sidebar/components/status/status.vue
'
;
import
{
healthStatus
,
healthStatus
ColorMap
,
healthStatus
TextMap
}
from
'
ee/sidebar/constants
'
;
import
{
healthStatus
,
healthStatusTextMap
}
from
'
ee/sidebar/constants
'
;
const
getStatusText
=
wrapper
=>
wrapper
.
find
(
'
.value
'
).
text
();
const
getStatusText
=
wrapper
=>
wrapper
.
find
(
'
.value
.text-plain
'
).
text
();
const
getTooltipText
=
wrapper
=>
wrapper
.
find
(
GlTooltip
).
text
();
const
getStatusIconCssClasses
=
wrapper
=>
wrapper
.
find
(
'
[name="severity-low"]
'
).
classes
();
const
getEditButton
=
wrapper
=>
wrapper
.
find
({
ref
:
'
editButton
'
});
const
getRemoveStatusButton
=
wrapper
=>
wrapper
.
find
(
GlDeprecatedButton
);
const
getEditForm
=
wrapper
=>
wrapper
.
find
(
'
form
'
);
const
getRadioInputs
=
wrapper
=>
wrapper
.
findAll
(
'
input[type="radio"]
'
);
const
getDropdownElement
=
wrapper
=>
wrapper
.
find
(
GlDropdown
);
const
getR
adioComponent
=
wrapper
=>
wrapper
.
find
(
GlFormRadioGroup
);
const
getR
emoveStatusItem
=
wrapper
=>
wrapper
.
find
(
GlDropdownItem
);
describe
(
'
Status
'
,
()
=>
{
let
wrapper
;
...
...
@@ -41,8 +35,7 @@ describe('Status', () => {
it
(
'
shows the text "Status"
'
,
()
=>
{
shallowMountStatus
();
expect
(
wrapper
.
find
(
'
.title
'
).
text
()).
toBe
(
'
Status
'
);
expect
(
wrapper
.
find
(
'
.title
'
).
text
()).
toBe
(
'
Health status
'
);
});
describe
(
'
loading icon
'
,
()
=>
{
...
...
@@ -89,18 +82,7 @@ describe('Status', () => {
});
});
describe
(
'
remove status button
'
,
()
=>
{
it
(
'
is hidden when there is no status
'
,
()
=>
{
const
props
=
{
isEditable
:
true
,
status
:
''
,
};
shallowMountStatus
(
props
);
expect
(
getRemoveStatusButton
(
wrapper
).
exists
()).
toBe
(
false
);
});
describe
(
'
remove status dropdown item
'
,
()
=>
{
it
(
'
is displayed when there is a status
'
,
()
=>
{
const
props
=
{
isEditable
:
true
,
...
...
@@ -109,10 +91,14 @@ describe('Status', () => {
shallowMountStatus
(
props
);
expect
(
getRemoveStatusButton
(
wrapper
).
exists
()).
toBe
(
true
);
wrapper
.
vm
.
isDropdownShowing
=
true
;
wrapper
.
vm
.
$nextTick
(()
=>
{
expect
(
getRemoveStatusItem
(
wrapper
).
exists
()).
toBe
(
true
);
});
});
it
(
'
emits an on
StatusChange
event with argument null when clicked
'
,
()
=>
{
it
(
'
emits an on
DropdownClick
event with argument null when clicked
'
,
()
=>
{
const
props
=
{
isEditable
:
true
,
status
:
healthStatus
.
AT_RISK
,
...
...
@@ -120,9 +106,13 @@ describe('Status', () => {
shallowMountStatus
(
props
);
getRemoveStatusButton
(
wrapper
).
vm
.
$emit
(
'
click
'
)
;
wrapper
.
vm
.
isDropdownShowing
=
true
;
expect
(
wrapper
.
emitted
().
onStatusChange
[
0
]).
toEqual
([
null
]);
wrapper
.
vm
.
$nextTick
(()
=>
{
getRemoveStatusItem
(
wrapper
).
vm
.
$emit
(
'
click
'
,
{
preventDefault
:
()
=>
null
});
expect
(
wrapper
.
emitted
().
onDropdownClick
[
0
]).
toEqual
([
null
]);
});
});
});
...
...
@@ -137,11 +127,11 @@ describe('Status', () => {
});
it
(
'
shows "None"
'
,
()
=>
{
expect
(
getStatusText
(
wrapper
)).
toBe
(
'
None
'
);
expect
(
wrapper
.
find
(
'
.no-value
'
).
text
(
)).
toBe
(
'
None
'
);
});
it
(
'
shows "Status" in the tooltip
'
,
()
=>
{
expect
(
getTooltipText
(
wrapper
)).
toBe
(
'
S
tatus
'
);
expect
(
getTooltipText
(
wrapper
)).
toBe
(
'
Health s
tatus
'
);
});
});
...
...
@@ -159,24 +149,22 @@ describe('Status', () => {
});
it
(
`shows "Status:
${
healthStatusTextMap
[
statusValue
]}
" in the tooltip`
,
()
=>
{
expect
(
getTooltipText
(
wrapper
)).
toBe
(
`Status:
${
healthStatusTextMap
[
statusValue
]}
`
);
});
it
(
`uses
${
healthStatusColorMap
[
statusValue
]}
color for the status icon`
,
()
=>
{
expect
(
getStatusIconCssClasses
(
wrapper
)).
toContain
(
healthStatusColorMap
[
statusValue
]);
expect
(
getTooltipText
(
wrapper
)).
toBe
(
`Health status:
${
healthStatusTextMap
[
statusValue
]}
`
);
});
});
});
describe
(
'
status
edit form
'
,
()
=>
{
describe
(
'
status
dropdown
'
,
()
=>
{
it
(
'
is hidden by default
'
,
()
=>
{
const
props
=
{
isEditable
:
true
,
};
shallowMountStatus
(
props
);
mountStatus
(
props
);
const
dropdown
=
wrapper
.
find
(
'
.dropdown
'
);
expect
(
getEditForm
(
wrapper
).
exists
()).
toBe
(
false
);
expect
(
dropdown
.
classes
()).
toContain
(
'
d-none
'
);
});
describe
(
'
when hidden
'
,
()
=>
{
...
...
@@ -185,14 +173,14 @@ describe('Status', () => {
isEditable
:
true
,
};
shallowM
ountStatus
(
props
);
m
ountStatus
(
props
);
});
it
(
'
shows the
form
when the Edit button is clicked
'
,
()
=>
{
it
(
'
shows the
dropdown
when the Edit button is clicked
'
,
()
=>
{
getEditButton
(
wrapper
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
expect
(
getEditForm
(
wrapper
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
'
.dropdown
'
).
classes
()).
toContain
(
'
show
'
);
});
});
});
...
...
@@ -205,47 +193,43 @@ describe('Status', () => {
shallowMountStatus
(
props
);
wrapper
.
setData
({
is
Form
Showing
:
true
});
wrapper
.
setData
({
is
Dropdown
Showing
:
true
});
});
it
(
'
shows text to ask the user to pick an option
'
,
()
=>
{
const
message
=
'
Choose which status most accurately reflects the current state of this issue:
'
;
const
message
=
'
Assign health status
'
;
expect
(
get
EditForm
(
wrapper
)
.
find
(
'
p
'
)
get
DropdownElement
(
wrapper
)
.
find
(
'
.health-title
'
)
.
text
(),
).
toContain
(
message
);
});
it
(
'
hides form when the
Edit
button is clicked
'
,
()
=>
{
it
(
'
hides form when the
`edit`
button is clicked
'
,
()
=>
{
getEditButton
(
wrapper
).
trigger
(
'
click
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
expect
(
getEditForm
(
wrapper
).
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
(
'
.dropdown
'
).
classes
()).
toContain
(
'
d-none
'
);
});
});
it
(
'
hides form when
the Cancel button
is clicked
'
,
()
=>
{
const
button
=
getEditForm
(
wrapper
).
find
(
'
[type="button"]
'
);
it
(
'
hides form when
a dropdown item
is clicked
'
,
()
=>
{
const
dropdownItem
=
wrapper
.
findAll
(
GlDropdownItem
).
at
(
1
);
button
.
vm
.
$emit
(
'
click
'
);
dropdownItem
.
vm
.
$emit
(
'
click
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
expect
(
getEditForm
(
wrapper
).
exists
()).
toBe
(
false
);
});
});
it
(
'
hides form when the form is submitted
'
,
()
=>
{
getEditForm
(
wrapper
).
trigger
(
'
submit
'
);
return
Vue
.
nextTick
().
then
(()
=>
{
expect
(
getEditForm
(
wrapper
).
exists
()).
toBe
(
false
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
'
.dropdown
'
).
classes
()).
toContain
(
'
d-none
'
);
});
});
});
describe
(
'
radio buttons
'
,
()
=>
{
describe
(
'
dropdown
'
,
()
=>
{
const
getIterableArray
=
arr
=>
{
return
arr
.
map
((
value
,
index
)
=>
[
value
,
index
]);
};
beforeEach
(()
=>
{
const
props
=
{
isEditable
:
true
,
...
...
@@ -253,29 +237,37 @@ describe('Status', () => {
mountStatus
(
props
);
wrapper
.
setData
({
is
Form
Showing
:
true
});
wrapper
.
setData
({
is
Dropdown
Showing
:
true
});
});
it
(
'
shows
3 radio button
s
'
,
()
=>
{
expect
(
getRadioInputs
(
wrapper
).
length
).
toBe
(
3
);
it
(
'
shows
4 dropdown item
s
'
,
()
=>
{
expect
(
wrapper
.
findAll
(
GlDropdownItem
).
length
).
toBe
(
4
);
});
// Test that "On track", "Needs attention", and "At risk" are displayed
it
.
each
(
Object
.
values
(
healthStatusTextMap
))(
'
shows "%s" text
'
,
statusText
=>
{
expect
(
getRadioComponent
(
wrapper
).
text
()).
toContain
(
statusText
);
});
it
.
each
(
getIterableArray
(
Object
.
values
(
healthStatusTextMap
)))(
'
shows "%s" text
'
,
(
statusText
,
index
)
=>
{
expect
(
wrapper
.
findAll
(
GlDropdownItem
)
.
at
(
index
+
1
)
// +1 in index to account for 1st item as `No status`
.
text
(),
).
toContain
(
statusText
);
},
);
// Test that "onTrack", "needsAttention", and "atRisk" values are emitted when form is submitted
it
.
each
(
Object
.
values
(
healthStatus
))(
'
emits onStatusChange event with argument "%s" when user selects the option and submits form
'
,
status
=>
{
getEditForm
(
wrapper
)
.
find
(
`input[value="
${
status
}
"]`
)
.
trigger
(
'
click
'
);
it
.
each
(
getIterableArray
(
Object
.
values
(
healthStatus
)))(
'
emits onFormSubmit event with argument "%s" when user selects the option and submits form
'
,
(
status
,
index
)
=>
{
wrapper
.
findAll
(
GlDropdownItem
)
.
at
(
index
+
1
)
.
vm
.
$emit
(
'
click
'
,
{
preventDefault
:
()
=>
null
});
return
Vue
.
nextTick
().
then
(()
=>
{
getEditForm
(
wrapper
).
trigger
(
'
submit
'
);
expect
(
wrapper
.
emitted
().
onStatusChange
[
0
]).
toEqual
([
status
]);
expect
(
wrapper
.
emitted
().
onDropdownClick
[
0
]).
toEqual
([
status
]);
});
},
);
...
...
locale/gitlab.pot
View file @
4a8b8929
...
...
@@ -3850,9 +3850,6 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node"
msgstr ""
msgid "Choose which status most accurately reflects the current state of this issue:"
msgstr ""
msgid "Choose your framework"
msgstr ""
...
...
@@ -18040,6 +18037,9 @@ msgstr ""
msgid "Select groups to replicate"
msgstr ""
msgid "Select health status"
msgstr ""
msgid "Select labels"
msgstr ""
...
...
@@ -18576,16 +18576,22 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
msgid "Sidebar|Assign health status"
msgstr ""
msgid "Sidebar|Change weight"
msgstr ""
msgid "Sidebar|
None
"
msgid "Sidebar|
Health status
"
msgstr ""
msgid "Sidebar|
Only numeral characters allowed
"
msgid "Sidebar|
No status
"
msgstr ""
msgid "Sidebar|Status"
msgid "Sidebar|None"
msgstr ""
msgid "Sidebar|Only numeral characters allowed"
msgstr ""
msgid "Sidebar|Weight"
...
...
@@ -24957,9 +24963,6 @@ msgstr ""
msgid "remove due date"
msgstr ""
msgid "remove status"
msgstr ""
msgid "remove weight"
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