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
d213000c
Commit
d213000c
authored
Apr 06, 2021
by
Florie Guibert
Committed by
Natalia Tepluhina
Apr 06, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Epic board sidebar - Edit epic labels [RUN AS-IF-FOSS]
parent
ca836edd
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
487 additions
and
155 deletions
+487
-155
app/assets/javascripts/boards/components/board_content.vue
app/assets/javascripts/boards/components/board_content.vue
+10
-1
app/assets/javascripts/boards/components/board_content_sidebar.vue
...s/javascripts/boards/components/board_content_sidebar.vue
+6
-7
app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
...ipts/boards/components/sidebar/board_sidebar_due_date.vue
+3
-3
app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
...s/boards/components/sidebar/board_sidebar_issue_title.vue
+1
-1
app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
...boards/components/sidebar/board_sidebar_labels_select.vue
+6
-6
app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
...rds/components/sidebar/board_sidebar_milestone_select.vue
+8
-8
app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
.../boards/components/sidebar/board_sidebar_subscription.vue
+5
-5
app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue
.../boards/components/sidebar/board_sidebar_time_tracker.vue
+5
-5
app/assets/javascripts/boards/stores/actions.js
app/assets/javascripts/boards/stores/actions.js
+28
-24
app/assets/javascripts/boards/stores/getters.js
app/assets/javascripts/boards/stores/getters.js
+3
-3
app/assets/javascripts/boards/stores/mutation_types.js
app/assets/javascripts/boards/stores/mutation_types.js
+1
-1
app/assets/javascripts/boards/stores/mutations.js
app/assets/javascripts/boards/stores/mutations.js
+3
-3
app/assets/stylesheets/page_bundles/boards.scss
app/assets/stylesheets/page_bundles/boards.scss
+2
-2
app/assets/stylesheets/pages/issuable.scss
app/assets/stylesheets/pages/issuable.scss
+1
-1
app/views/shared/boards/components/_sidebar.html.haml
app/views/shared/boards/components/_sidebar.html.haml
+1
-1
ee/app/assets/javascripts/boards/components/epic_board_content_sidebar.vue
...ascripts/boards/components/epic_board_content_sidebar.vue
+45
-0
ee/app/assets/javascripts/boards/components/sidebar/board_sidebar_epic_select.vue
...s/boards/components/sidebar/board_sidebar_epic_select.vue
+2
-2
ee/app/assets/javascripts/boards/components/sidebar/board_sidebar_weight_input.vue
.../boards/components/sidebar/board_sidebar_weight_input.vue
+6
-6
ee/app/assets/javascripts/boards/graphql/update_epic_labels.mutation.graphql
...cripts/boards/graphql/update_epic_labels.mutation.graphql
+16
-0
ee/app/assets/javascripts/boards/stores/actions.js
ee/app/assets/javascripts/boards/stores/actions.js
+42
-8
ee/spec/features/boards/new_issue_spec.rb
ee/spec/features/boards/new_issue_spec.rb
+1
-1
ee/spec/features/epic_boards/epic_boards_sidebar_spec.rb
ee/spec/features/epic_boards/epic_boards_sidebar_spec.rb
+78
-0
ee/spec/frontend/boards/components/board_content_sidebar_spec.js
.../frontend/boards/components/board_content_sidebar_spec.js
+1
-1
ee/spec/frontend/boards/components/epic_board_content_sidebar_spec.js
...tend/boards/components/epic_board_content_sidebar_spec.js
+96
-0
ee/spec/frontend/boards/mock_data.js
ee/spec/frontend/boards/mock_data.js
+1
-1
ee/spec/frontend/boards/stores/actions_spec.js
ee/spec/frontend/boards/stores/actions_spec.js
+60
-14
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/features/boards/new_issue_spec.rb
spec/features/boards/new_issue_spec.rb
+2
-2
spec/frontend/boards/components/board_content_sidebar_spec.js
.../frontend/boards/components/board_content_sidebar_spec.js
+1
-1
spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
...ds/components/sidebar/board_sidebar_labels_select_spec.js
+7
-7
spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
...rds/components/sidebar/board_sidebar_subscription_spec.js
+5
-5
spec/frontend/boards/stores/actions_spec.js
spec/frontend/boards/stores/actions_spec.js
+19
-19
spec/frontend/boards/stores/getters_spec.js
spec/frontend/boards/stores/getters_spec.js
+8
-6
spec/frontend/boards/stores/mutations_spec.js
spec/frontend/boards/stores/mutations_spec.js
+5
-5
spec/support/shared_examples/features/sidebar_shared_examples.rb
...pport/shared_examples/features/sidebar_shared_examples.rb
+6
-6
No files found.
app/assets/javascripts/boards/components/board_content.vue
View file @
d213000c
...
...
@@ -18,6 +18,8 @@ export default {
?
BoardColumn
:
BoardColumnDeprecated
,
BoardContentSidebar
:
()
=>
import
(
'
~/boards/components/board_content_sidebar.vue
'
),
EpicBoardContentSidebar
:
()
=>
import
(
'
ee_component/boards/components/epic_board_content_sidebar.vue
'
),
EpicsSwimlanes
:
()
=>
import
(
'
ee_component/boards/components/epics_swimlanes.vue
'
),
GlAlert
,
},
...
...
@@ -133,7 +135,14 @@ export default {
<board-content-sidebar
v-if=
"isSwimlanesOn || glFeatures.graphqlBoardLists"
class=
"issue-boards-sidebar"
class=
"boards-sidebar"
data-testid=
"issue-boards-sidebar"
/>
<epic-board-content-sidebar
v-else-if=
"isEpicBoard"
class=
"boards-sidebar"
data-testid=
"epic-boards-sidebar"
/>
</div>
</
template
>
app/assets/javascripts/boards/components/board_content_sidebar.vue
View file @
d213000c
...
...
@@ -34,7 +34,7 @@ export default {
computed
:
{
...
mapGetters
([
'
isSidebarOpen
'
,
'
active
Issue
'
,
'
active
BoardItem
'
,
'
groupPathForActiveIssue
'
,
'
projectPathForActiveIssue
'
,
]),
...
...
@@ -46,13 +46,13 @@ export default {
return
this
.
isIssuableSidebar
&&
this
.
isSidebarOpen
;
},
fullPath
()
{
return
this
.
active
Issue
?.
referencePath
?.
split
(
'
#
'
)[
0
]
||
''
;
return
this
.
active
BoardItem
?.
referencePath
?.
split
(
'
#
'
)[
0
]
||
''
;
},
},
methods
:
{
...
mapActions
([
'
toggleBoardItem
'
,
'
setAssignees
'
]),
handleClose
()
{
this
.
toggleBoardItem
({
boardItem
:
this
.
active
Issue
,
sidebarType
:
this
.
sidebarType
});
this
.
toggleBoardItem
({
boardItem
:
this
.
active
BoardItem
,
sidebarType
:
this
.
sidebarType
});
},
},
};
...
...
@@ -61,7 +61,6 @@ export default {
<
template
>
<gl-drawer
v-if=
"showSidebar"
data-testid=
"sidebar-drawer"
:open=
"isSidebarOpen"
:header-height=
"$options.headerHeight"
@
close=
"handleClose"
...
...
@@ -70,9 +69,9 @@ export default {
<
template
#default
>
<board-sidebar-issue-title
/>
<sidebar-assignees-widget
:iid=
"active
Issue
.iid"
:iid=
"active
BoardItem
.iid"
:full-path=
"fullPath"
:initial-assignees=
"active
Issue
.assignees"
:initial-assignees=
"active
BoardItem
.assignees"
class=
"assignee"
@
assignees-updated=
"setAssignees"
/>
...
...
@@ -80,7 +79,7 @@ export default {
<div>
<board-sidebar-milestone-select
/>
<sidebar-iteration-widget
:iid=
"active
Issue
.iid"
:iid=
"active
BoardItem
.iid"
:workspace-path=
"projectPathForActiveIssue"
:iterations-workspace-path=
"groupPathForActiveIssue"
:issuable-type=
"issuableType"
...
...
app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
View file @
d213000c
...
...
@@ -18,16 +18,16 @@ export default {
};
},
computed
:
{
...
mapGetters
([
'
active
Issue
'
,
'
projectPathForActiveIssue
'
]),
...
mapGetters
([
'
active
BoardItem
'
,
'
projectPathForActiveIssue
'
]),
hasDueDate
()
{
return
this
.
active
Issue
.
dueDate
!=
null
;
return
this
.
active
BoardItem
.
dueDate
!=
null
;
},
parsedDueDate
()
{
if
(
!
this
.
hasDueDate
)
{
return
null
;
}
return
parsePikadayDate
(
this
.
active
Issue
.
dueDate
);
return
parsePikadayDate
(
this
.
active
BoardItem
.
dueDate
);
},
formattedDueDate
()
{
if
(
!
this
.
hasDueDate
)
{
...
...
app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
View file @
d213000c
...
...
@@ -27,7 +27,7 @@ export default {
};
},
computed
:
{
...
mapGetters
({
issue
:
'
active
Issue
'
}),
...
mapGetters
({
issue
:
'
active
BoardItem
'
}),
pendingChangesStorageKey
()
{
return
this
.
getPendingChangesKey
(
this
.
issue
);
},
...
...
app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
View file @
d213000c
...
...
@@ -21,9 +21,9 @@ export default {
};
},
computed
:
{
...
mapGetters
([
'
active
Issue
'
,
'
projectPathForActiveIssue
'
]),
...
mapGetters
([
'
active
BoardItem
'
,
'
projectPathForActiveIssue
'
]),
selectedLabels
()
{
const
{
labels
=
[]
}
=
this
.
active
Issue
;
const
{
labels
=
[]
}
=
this
.
active
BoardItem
;
return
labels
.
map
((
label
)
=>
({
...
label
,
...
...
@@ -31,7 +31,7 @@ export default {
}));
},
issueLabels
()
{
const
{
labels
=
[]
}
=
this
.
active
Issue
;
const
{
labels
=
[]
}
=
this
.
active
BoardItem
;
return
labels
.
map
((
label
)
=>
({
...
label
,
...
...
@@ -40,7 +40,7 @@ export default {
},
},
methods
:
{
...
mapActions
([
'
setActive
Issue
Labels
'
]),
...
mapActions
([
'
setActive
BoardItem
Labels
'
]),
async
setLabels
(
payload
)
{
this
.
loading
=
true
;
this
.
$refs
.
sidebarItem
.
collapse
();
...
...
@@ -52,7 +52,7 @@ export default {
.
map
((
label
)
=>
label
.
id
);
const
input
=
{
addLabelIds
,
removeLabelIds
,
projectPath
:
this
.
projectPathForActiveIssue
};
await
this
.
setActive
Issue
Labels
(
input
);
await
this
.
setActive
BoardItem
Labels
(
input
);
}
catch
(
e
)
{
createFlash
({
message
:
__
(
'
An error occurred while updating labels.
'
)
});
}
finally
{
...
...
@@ -65,7 +65,7 @@ export default {
try
{
const
removeLabelIds
=
[
getIdFromGraphQLId
(
id
)];
const
input
=
{
removeLabelIds
,
projectPath
:
this
.
projectPathForActiveIssue
};
await
this
.
setActive
Issue
Labels
(
input
);
await
this
.
setActive
BoardItem
Labels
(
input
);
}
catch
(
e
)
{
createFlash
({
message
:
__
(
'
An error occurred when removing the label.
'
)
});
}
finally
{
...
...
app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
View file @
d213000c
...
...
@@ -56,20 +56,20 @@ export default {
},
},
computed
:
{
...
mapGetters
([
'
active
Issue
'
]),
...
mapGetters
([
'
active
BoardItem
'
]),
hasMilestone
()
{
return
this
.
active
Issue
.
milestone
!==
null
;
return
this
.
active
BoardItem
.
milestone
!==
null
;
},
groupFullPath
()
{
const
{
referencePath
=
''
}
=
this
.
active
Issue
;
const
{
referencePath
=
''
}
=
this
.
active
BoardItem
;
return
referencePath
.
slice
(
0
,
referencePath
.
indexOf
(
'
/
'
));
},
projectPath
()
{
const
{
referencePath
=
''
}
=
this
.
active
Issue
;
const
{
referencePath
=
''
}
=
this
.
active
BoardItem
;
return
referencePath
.
slice
(
0
,
referencePath
.
indexOf
(
'
#
'
));
},
dropdownText
()
{
return
this
.
active
Issue
.
milestone
?.
title
??
this
.
$options
.
i18n
.
noMilestone
;
return
this
.
active
BoardItem
.
milestone
?.
title
??
this
.
$options
.
i18n
.
noMilestone
;
},
},
methods
:
{
...
...
@@ -118,7 +118,7 @@ export default {
@
close=
"handleClose"
>
<template
v-if=
"hasMilestone"
#collapsed
>
<strong
class=
"gl-text-gray-900"
>
{{
active
Issue
.
milestone
.
title
}}
</strong>
<strong
class=
"gl-text-gray-900"
>
{{
active
BoardItem
.
milestone
.
title
}}
</strong>
</
template
>
<gl-dropdown
ref=
"dropdown"
...
...
@@ -131,7 +131,7 @@ export default {
<gl-dropdown-item
data-testid=
"no-milestone-item"
:is-check-item=
"true"
:is-checked=
"!active
Issue
.milestone"
:is-checked=
"!active
BoardItem
.milestone"
@
click=
"setMilestone(null)"
>
{{ $options.i18n.noMilestone }}
...
...
@@ -143,7 +143,7 @@ export default {
v-for=
"milestone in milestones"
:key=
"milestone.id"
:is-check-item=
"true"
:is-checked=
"active
Issue.milestone && milestone.id === activeIssue
.milestone.id"
:is-checked=
"active
BoardItem.milestone && milestone.id === activeBoardItem
.milestone.id"
data-testid=
"milestone-item"
@
click=
"setMilestone(milestone.id)"
>
...
...
app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
View file @
d213000c
...
...
@@ -27,9 +27,9 @@ export default {
};
},
computed
:
{
...
mapGetters
([
'
active
Issue
'
,
'
projectPathForActiveIssue
'
]),
...
mapGetters
([
'
active
BoardItem
'
,
'
projectPathForActiveIssue
'
]),
notificationText
()
{
return
this
.
active
Issue
.
emailsDisabled
return
this
.
active
BoardItem
.
emailsDisabled
?
this
.
$options
.
i18n
.
header
.
subscribeDisabledDescription
:
this
.
$options
.
i18n
.
header
.
title
;
},
...
...
@@ -41,7 +41,7 @@ export default {
try
{
await
this
.
setActiveIssueSubscribed
({
subscribed
:
!
this
.
active
Issue
.
subscribed
,
subscribed
:
!
this
.
active
BoardItem
.
subscribed
,
projectPath
:
this
.
projectPathForActiveIssue
,
});
}
catch
(
error
)
{
...
...
@@ -61,8 +61,8 @@ export default {
>
<span
data-testid=
"notification-header-text"
>
{{
notificationText
}}
</span>
<gl-toggle
v-if=
"!active
Issue
.emailsDisabled"
:value=
"active
Issue
.subscribed"
v-if=
"!active
BoardItem
.emailsDisabled"
:value=
"active
BoardItem
.subscribed"
:is-loading=
"loading"
:label=
"$options.i18n.header.title"
label-position=
"hidden"
...
...
app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue
View file @
d213000c
...
...
@@ -8,17 +8,17 @@ export default {
},
inject
:
[
'
timeTrackingLimitToHours
'
],
computed
:
{
...
mapGetters
([
'
active
Issue
'
]),
...
mapGetters
([
'
active
BoardItem
'
]),
},
};
</
script
>
<
template
>
<issuable-time-tracker
:time-estimate=
"active
Issue
.timeEstimate"
:time-spent=
"active
Issue
.totalTimeSpent"
:human-time-estimate=
"active
Issue
.humanTimeEstimate"
:human-time-spent=
"active
Issue
.humanTotalTimeSpent"
:time-estimate=
"active
BoardItem
.timeEstimate"
:time-spent=
"active
BoardItem
.totalTimeSpent"
:human-time-estimate=
"active
BoardItem
.humanTimeEstimate"
:human-time-spent=
"active
BoardItem
.humanTotalTimeSpent"
:limit-to-hours=
"timeTrackingLimitToHours"
:show-collapsed=
"false"
/>
...
...
app/assets/javascripts/boards/stores/actions.js
View file @
d213000c
...
...
@@ -371,20 +371,20 @@ export default {
},
setAssignees
:
({
commit
,
getters
},
assigneeUsernames
)
=>
{
commit
(
'
UPDATE_
ISSUE
_BY_ID
'
,
{
i
ssueId
:
getters
.
activeIssue
.
id
,
commit
(
'
UPDATE_
BOARD_ITEM
_BY_ID
'
,
{
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
assignees
'
,
value
:
assigneeUsernames
,
});
},
setActiveIssueMilestone
:
async
({
commit
,
getters
},
input
)
=>
{
const
{
active
Issue
}
=
getters
;
const
{
active
BoardItem
}
=
getters
;
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
issueSetMilestoneMutation
,
variables
:
{
input
:
{
iid
:
String
(
active
Issue
.
iid
),
iid
:
String
(
active
BoardItem
.
iid
),
milestoneId
:
getIdFromGraphQLId
(
input
.
milestoneId
),
projectPath
:
input
.
projectPath
,
},
...
...
@@ -395,8 +395,8 @@ export default {
throw
new
Error
(
data
.
updateIssue
.
errors
);
}
commit
(
types
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssueId
:
activeIssue
.
id
,
commit
(
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
temId
:
activeBoardItem
.
id
,
prop
:
'
milestone
'
,
value
:
data
.
updateIssue
.
issue
.
milestone
,
});
...
...
@@ -447,13 +447,17 @@ export default {
.
catch
(()
=>
commit
(
types
.
ADD_ISSUE_TO_LIST_FAILURE
,
{
list
,
issueId
:
issueInput
.
id
}));
},
setActiveBoardItemLabels
:
({
dispatch
},
params
)
=>
{
dispatch
(
'
setActiveIssueLabels
'
,
params
);
},
setActiveIssueLabels
:
async
({
commit
,
getters
},
input
)
=>
{
const
{
active
Issue
}
=
getters
;
const
{
active
BoardItem
}
=
getters
;
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
issueSetLabelsMutation
,
variables
:
{
input
:
{
iid
:
String
(
active
Issue
.
iid
),
iid
:
String
(
active
BoardItem
.
iid
),
addLabelIds
:
input
.
addLabelIds
??
[],
removeLabelIds
:
input
.
removeLabelIds
??
[],
projectPath
:
input
.
projectPath
,
...
...
@@ -465,20 +469,20 @@ export default {
throw
new
Error
(
data
.
updateIssue
.
errors
);
}
commit
(
types
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssueId
:
activeIssue
.
id
,
commit
(
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
temId
:
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
data
.
updateIssue
.
issue
.
labels
.
nodes
,
});
},
setActiveIssueDueDate
:
async
({
commit
,
getters
},
input
)
=>
{
const
{
active
Issue
}
=
getters
;
const
{
active
BoardItem
}
=
getters
;
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
issueSetDueDateMutation
,
variables
:
{
input
:
{
iid
:
String
(
active
Issue
.
iid
),
iid
:
String
(
active
BoardItem
.
iid
),
projectPath
:
input
.
projectPath
,
dueDate
:
input
.
dueDate
,
},
...
...
@@ -489,8 +493,8 @@ export default {
throw
new
Error
(
data
.
updateIssue
.
errors
);
}
commit
(
types
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssueId
:
activeIssue
.
id
,
commit
(
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
temId
:
activeBoardItem
.
id
,
prop
:
'
dueDate
'
,
value
:
data
.
updateIssue
.
issue
.
dueDate
,
});
...
...
@@ -501,7 +505,7 @@ export default {
mutation
:
issueSetSubscriptionMutation
,
variables
:
{
input
:
{
iid
:
String
(
getters
.
active
Issue
.
iid
),
iid
:
String
(
getters
.
active
BoardItem
.
iid
),
projectPath
:
input
.
projectPath
,
subscribedState
:
input
.
subscribed
,
},
...
...
@@ -512,20 +516,20 @@ export default {
throw
new
Error
(
data
.
issueSetSubscription
.
errors
);
}
commit
(
types
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssueId
:
getters
.
activeIssue
.
id
,
commit
(
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
subscribed
'
,
value
:
data
.
issueSetSubscription
.
issue
.
subscribed
,
});
},
setActiveIssueTitle
:
async
({
commit
,
getters
},
input
)
=>
{
const
{
active
Issue
}
=
getters
;
const
{
active
BoardItem
}
=
getters
;
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
issueSetTitleMutation
,
variables
:
{
input
:
{
iid
:
String
(
active
Issue
.
iid
),
iid
:
String
(
active
BoardItem
.
iid
),
projectPath
:
input
.
projectPath
,
title
:
input
.
title
,
},
...
...
@@ -536,8 +540,8 @@ export default {
throw
new
Error
(
data
.
updateIssue
.
errors
);
}
commit
(
types
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssueId
:
activeIssue
.
id
,
commit
(
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
temId
:
activeBoardItem
.
id
,
prop
:
'
title
'
,
value
:
data
.
updateIssue
.
issue
.
title
,
});
...
...
@@ -578,10 +582,10 @@ export default {
const
{
selectedBoardItems
}
=
state
;
const
index
=
selectedBoardItems
.
indexOf
(
boardItem
);
// If user already selected an item (active
Issue
) without using mult-select,
// If user already selected an item (active
BoardItem
) without using mult-select,
// include that item in the selection and unset state.ActiveId to hide the sidebar.
if
(
getters
.
active
Issue
)
{
commit
(
types
.
ADD_BOARD_ITEM_TO_SELECTION
,
getters
.
active
Issue
);
if
(
getters
.
active
BoardItem
)
{
commit
(
types
.
ADD_BOARD_ITEM_TO_SELECTION
,
getters
.
active
BoardItem
);
dispatch
(
'
unsetActiveId
'
);
}
...
...
app/assets/javascripts/boards/stores/getters.js
View file @
d213000c
...
...
@@ -15,17 +15,17 @@ export default {
return
listItemsIds
.
map
((
id
)
=>
getters
.
getBoardItemById
(
id
));
},
active
Issue
:
(
state
)
=>
{
active
BoardItem
:
(
state
)
=>
{
return
state
.
boardItems
[
state
.
activeId
]
||
{};
},
groupPathForActiveIssue
:
(
_
,
getters
)
=>
{
const
{
referencePath
=
''
}
=
getters
.
active
Issue
;
const
{
referencePath
=
''
}
=
getters
.
active
BoardItem
;
return
referencePath
.
slice
(
0
,
referencePath
.
indexOf
(
'
/
'
));
},
projectPathForActiveIssue
:
(
_
,
getters
)
=>
{
const
{
referencePath
=
''
}
=
getters
.
active
Issue
;
const
{
referencePath
=
''
}
=
getters
.
active
BoardItem
;
return
referencePath
.
slice
(
0
,
referencePath
.
indexOf
(
'
#
'
));
},
...
...
app/assets/javascripts/boards/stores/mutation_types.js
View file @
d213000c
...
...
@@ -36,7 +36,7 @@ export const REMOVE_ISSUE_FROM_LIST = 'REMOVE_ISSUE_FROM_LIST';
export
const
SET_CURRENT_PAGE
=
'
SET_CURRENT_PAGE
'
;
export
const
TOGGLE_EMPTY_STATE
=
'
TOGGLE_EMPTY_STATE
'
;
export
const
SET_ACTIVE_ID
=
'
SET_ACTIVE_ID
'
;
export
const
UPDATE_
ISSUE_BY_ID
=
'
UPDATE_ISSUE
_BY_ID
'
;
export
const
UPDATE_
BOARD_ITEM_BY_ID
=
'
UPDATE_BOARD_ITEM
_BY_ID
'
;
export
const
SET_ASSIGNEE_LOADING
=
'
SET_ASSIGNEE_LOADING
'
;
export
const
RESET_ISSUES
=
'
RESET_ISSUES
'
;
export
const
REQUEST_GROUP_PROJECTS
=
'
REQUEST_GROUP_PROJECTS
'
;
...
...
app/assets/javascripts/boards/stores/mutations.js
View file @
d213000c
...
...
@@ -158,13 +158,13 @@ export default {
});
},
[
mutationTypes
.
UPDATE_
ISSUE_BY_ID
]:
(
state
,
{
issue
Id
,
prop
,
value
})
=>
{
if
(
!
state
.
boardItems
[
i
ssue
Id
])
{
[
mutationTypes
.
UPDATE_
BOARD_ITEM_BY_ID
]:
(
state
,
{
item
Id
,
prop
,
value
})
=>
{
if
(
!
state
.
boardItems
[
i
tem
Id
])
{
/* eslint-disable-next-line @gitlab/require-i18n-strings */
throw
new
Error
(
'
No issue found.
'
);
}
Vue
.
set
(
state
.
boardItems
[
i
ssue
Id
],
prop
,
value
);
Vue
.
set
(
state
.
boardItems
[
i
tem
Id
],
prop
,
value
);
},
[
mutationTypes
.
SET_ASSIGNEE_LOADING
](
state
,
isLoading
)
{
...
...
app/assets/stylesheets/page_bundles/boards.scss
View file @
d213000c
...
...
@@ -365,7 +365,7 @@
margin
:
5px
;
}
.right-sidebar.
issue-
boards-sidebar
{
.right-sidebar.boards-sidebar
{
.gutter-toggle
{
bottom
:
15px
;
width
:
22px
;
...
...
@@ -462,7 +462,7 @@
overflow-x
:
scroll
;
}
.
issue-
boards-sidebar
{
.boards-sidebar
{
height
:
100%
;
top
:
0
;
}
...
...
app/assets/stylesheets/pages/issuable.scss
View file @
d213000c
...
...
@@ -287,7 +287,7 @@
padding-top
:
10px
;
}
&
:not
(
.
issue-
boards-sidebar
)
:not
([
data-signed-in
])
:not
([
data-always-show-toggle
])
{
&
:not
(
.boards-sidebar
)
:not
([
data-signed-in
])
:not
([
data-always-show-toggle
])
{
.issuable-sidebar-header
{
display
:
none
;
}
...
...
app/views/shared/boards/components/_sidebar.html.haml
View file @
d213000c
%board-sidebar
{
"inline-template"
=>
true
,
":current-user"
=>
(
UserSerializer
.
new
.
represent
(
current_user
)
||
{}).
to_json
}
%transition
{
name:
"boards-sidebar-slide"
}
%aside
.right-sidebar.right-sidebar-expanded.
issue-boards-sidebar
{
"v-show"
=>
"showSidebar"
,
'aria-label'
:
s_
(
'Boards|Board'
)
}
%aside
.right-sidebar.right-sidebar-expanded.
boards-sidebar
{
"v-show"
=>
"showSidebar"
,
'aria-label'
:
s_
(
'Boards|Board'
),
'data-testid'
:
'issue-boards-sidebar'
}
.issuable-sidebar
.block.issuable-sidebar-header.position-relative
%span
.issuable-header-text.hide-collapsed.float-left
...
...
ee/app/assets/javascripts/boards/components/epic_board_content_sidebar.vue
0 → 100644
View file @
d213000c
<
script
>
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
mapState
,
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
contentTop
}
from
'
~/lib/utils/common_utils
'
;
export
default
{
headerHeight
:
`
${
contentTop
()}
px`
,
components
:
{
GlDrawer
,
BoardSidebarLabelsSelect
,
},
computed
:
{
...
mapGetters
([
'
isSidebarOpen
'
,
'
activeBoardItem
'
]),
...
mapState
([
'
sidebarType
'
]),
isIssuableSidebar
()
{
return
this
.
sidebarType
===
ISSUABLE
;
},
showSidebar
()
{
return
this
.
isIssuableSidebar
&&
this
.
isSidebarOpen
;
},
},
methods
:
{
...
mapActions
([
'
toggleBoardItem
'
]),
handleClose
()
{
this
.
toggleBoardItem
({
boardItem
:
this
.
activeBoardItem
,
sidebarType
:
this
.
sidebarType
});
},
},
};
</
script
>
<
template
>
<gl-drawer
v-if=
"showSidebar"
:open=
"isSidebarOpen"
:header-height=
"$options.headerHeight"
@
close=
"handleClose"
>
<template
#header
>
{{
__
(
'
Epic details
'
)
}}
</
template
>
<
template
#default
>
<board-sidebar-labels-select
class=
"labels"
/>
</
template
>
</gl-drawer>
</template>
ee/app/assets/javascripts/boards/components/sidebar/board_sidebar_epic_select.vue
View file @
d213000c
...
...
@@ -26,9 +26,9 @@ export default {
inject
:
[
'
groupId
'
],
computed
:
{
...
mapState
([
'
epics
'
,
'
epicsCacheById
'
,
'
epicFetchInProgress
'
]),
...
mapGetters
([
'
active
Issue
'
,
'
projectPathForActiveIssue
'
]),
...
mapGetters
([
'
active
BoardItem
'
,
'
projectPathForActiveIssue
'
]),
epic
()
{
return
this
.
active
Issue
.
epic
;
return
this
.
active
BoardItem
.
epic
;
},
epicData
()
{
const
hasEpic
=
this
.
epic
!==
null
;
...
...
ee/app/assets/javascripts/boards/components/sidebar/board_sidebar_weight_input.vue
View file @
d213000c
...
...
@@ -23,13 +23,13 @@ export default {
};
},
computed
:
{
...
mapGetters
([
'
active
Issue
'
,
'
projectPathForActiveIssue
'
]),
...
mapGetters
([
'
active
BoardItem
'
,
'
projectPathForActiveIssue
'
]),
hasWeight
()
{
return
this
.
active
Issue
.
weight
>
0
;
return
this
.
active
BoardItem
.
weight
>
0
;
},
},
watch
:
{
active
Issue
:
{
active
BoardItem
:
{
handler
(
updatedIssue
)
{
this
.
weight
=
updatedIssue
.
weight
;
},
...
...
@@ -45,7 +45,7 @@ export default {
async
setWeight
(
provided
)
{
const
weight
=
provided
??
this
.
weight
;
if
(
this
.
loading
||
weight
===
this
.
active
Issue
.
weight
)
{
if
(
this
.
loading
||
weight
===
this
.
active
BoardItem
.
weight
)
{
return
;
}
...
...
@@ -55,7 +55,7 @@ export default {
await
this
.
setActiveIssueWeight
({
weight
,
projectPath
:
this
.
projectPathForActiveIssue
});
this
.
weight
=
weight
;
}
catch
(
e
)
{
this
.
weight
=
this
.
active
Issue
.
weight
;
this
.
weight
=
this
.
active
BoardItem
.
weight
;
createFlash
({
message
:
__
(
'
An error occurred when updating the issue weight
'
)
});
}
finally
{
this
.
loading
=
false
;
...
...
@@ -77,7 +77,7 @@ export default {
<strong
class=
"gl-text-gray-900 js-weight-weight-label-value"
data-qa-selector=
"weight_label_value"
>
{{
active
Issue
.
weight
}}
</strong
>
{{
active
BoardItem
.
weight
}}
</strong
>
<span
class=
"gl-mx-2"
>
-
</span>
<gl-button
...
...
ee/app/assets/javascripts/boards/graphql/update_epic_labels.mutation.graphql
0 → 100644
View file @
d213000c
mutation
updateEpic
(
$input
:
UpdateEpicInput
!)
{
updateEpic
(
input
:
$input
)
{
epic
{
id
labels
{
nodes
{
id
title
color
description
}
}
}
errors
}
}
ee/app/assets/javascripts/boards/stores/actions.js
View file @
d213000c
...
...
@@ -46,6 +46,7 @@ import projectBoardAssigneesQuery from '../graphql/project_board_assignees.query
import
projectBoardIterationsQuery
from
'
../graphql/project_board_iterations.query.graphql
'
;
import
projectBoardMilestonesQuery
from
'
../graphql/project_board_milestones.query.graphql
'
;
import
updateBoardEpicUserPreferencesMutation
from
'
../graphql/update_board_epic_user_preferences.mutation.graphql
'
;
import
updateEpicLabelsMutation
from
'
../graphql/update_epic_labels.mutation.graphql
'
;
import
boardsStoreEE
from
'
./boards_store_ee
'
;
import
*
as
types
from
'
./mutation_types
'
;
...
...
@@ -379,13 +380,13 @@ export default {
},
fetchEpicForActiveIssue
:
async
({
state
,
commit
,
getters
})
=>
{
if
(
!
getters
.
active
Issue
.
epic
)
{
if
(
!
getters
.
active
BoardItem
.
epic
)
{
return
false
;
}
const
{
epic
:
{
id
,
iid
},
}
=
getters
.
active
Issue
;
}
=
getters
.
active
BoardItem
;
if
(
state
.
epicsCacheById
[
id
])
{
return
false
;
...
...
@@ -421,7 +422,7 @@ export default {
mutation
:
issueSetEpicMutation
,
variables
:
{
input
:
{
iid
:
String
(
getters
.
active
Issue
.
iid
),
iid
:
String
(
getters
.
active
BoardItem
.
iid
),
epicId
,
projectPath
:
getters
.
projectPathForActiveIssue
,
},
...
...
@@ -439,8 +440,8 @@ export default {
commit
(
types
.
UPDATE_CACHED_EPICS
,
[
epic
]);
}
commit
(
typesCE
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssueId
:
getters
.
activeIssue
.
id
,
commit
(
typesCE
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
epic
'
,
value
:
epic
?
{
id
:
epic
.
id
,
iid
:
epic
.
iid
}
:
null
,
});
...
...
@@ -452,7 +453,7 @@ export default {
mutation
:
issueSetWeightMutation
,
variables
:
{
input
:
{
iid
:
String
(
getters
.
active
Issue
.
iid
),
iid
:
String
(
getters
.
active
BoardItem
.
iid
),
weight
:
input
.
weight
,
projectPath
:
input
.
projectPath
,
},
...
...
@@ -463,8 +464,8 @@ export default {
throw
new
Error
(
data
.
issueSetWeight
?.
errors
);
}
commit
(
typesCE
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssueId
:
getters
.
activeIssue
.
id
,
commit
(
typesCE
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
weight
'
,
value
:
data
.
issueSetWeight
.
issue
.
weight
,
});
...
...
@@ -765,4 +766,37 @@ export default {
throw
e
;
});
},
setActiveBoardItemLabels
:
({
getters
,
dispatch
},
params
)
=>
{
if
(
!
getters
.
isEpicBoard
)
{
dispatch
(
'
setActiveIssueLabels
'
,
params
);
}
else
{
dispatch
(
'
setActiveEpicLabels
'
,
params
);
}
},
setActiveEpicLabels
:
async
({
commit
,
getters
,
state
},
input
)
=>
{
const
{
activeBoardItem
}
=
getters
;
const
{
data
}
=
await
gqlClient
.
mutate
({
mutation
:
updateEpicLabelsMutation
,
variables
:
{
input
:
{
iid
:
String
(
activeBoardItem
.
iid
),
addLabelIds
:
input
.
addLabelIds
??
[],
removeLabelIds
:
input
.
removeLabelIds
??
[],
groupPath
:
state
.
fullPath
,
},
},
});
if
(
data
.
updateEpic
?.
errors
?.
length
>
0
)
{
throw
new
Error
(
data
.
updateEpic
.
errors
);
}
commit
(
typesCE
.
UPDATE_BOARD_ITEM_BY_ID
,
{
itemId
:
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
data
.
updateEpic
.
epic
.
labels
.
nodes
,
});
},
};
ee/spec/features/boards/new_issue_spec.rb
View file @
d213000c
...
...
@@ -36,7 +36,7 @@ RSpec.describe 'Issue Boards new issue', :js do
find
(
'.board-card'
).
click
end
page
.
within
(
first
(
'
.issue-boards-sidebar
'
))
do
page
.
within
(
first
(
'
[data-testid="issue-boards-sidebar"]
'
))
do
find
(
'.weight [data-testid="edit-button"]'
).
click
find
(
'.weight .form-control'
).
set
(
"10
\n
"
)
end
...
...
ee/spec/features/epic_boards/epic_boards_sidebar_spec.rb
0 → 100644
View file @
d213000c
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Epic boards sidebar'
,
:js
do
include
BoardHelpers
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:group
)
{
create
(
:group
,
:public
)
}
let_it_be
(
:bug
)
{
create
(
:group_label
,
group:
group
,
name:
'Bug'
)
}
let_it_be
(
:epic_board
)
{
create
(
:epic_board
,
group:
group
)
}
let_it_be
(
:backlog_list
)
{
create
(
:epic_list
,
epic_board:
epic_board
,
list_type: :backlog
)
}
let_it_be
(
:closed_list
)
{
create
(
:epic_list
,
epic_board:
epic_board
,
list_type: :closed
)
}
let_it_be
(
:epic1
)
{
create
(
:epic
,
group:
group
,
title:
'Epic1'
)
}
let
(
:card
)
{
find
(
'.board:nth-child(1)'
).
first
(
"[data-testid='board_card']"
)
}
before
do
stub_licensed_features
(
epics:
true
)
group
.
add_maintainer
(
user
)
sign_in
(
user
)
visit
group_epic_boards_path
(
group
)
wait_for_requests
end
it
'shows sidebar when clicking epic'
do
click_card
(
card
)
expect
(
page
).
to
have_selector
(
'[data-testid="epic-boards-sidebar"]'
)
end
it
'closes sidebar when clicking epic'
do
click_card
(
card
)
expect
(
page
).
to
have_selector
(
'[data-testid="epic-boards-sidebar"]'
)
click_card
(
card
)
expect
(
page
).
not_to
have_selector
(
'[data-testid="epic-boards-sidebar"]'
)
end
it
'closes sidebar when clicking close button'
do
click_card
(
card
)
expect
(
page
).
to
have_selector
(
'[data-testid="epic-boards-sidebar"]'
)
find
(
'[data-testid="close-icon"]'
).
click
expect
(
page
).
not_to
have_selector
(
'[data-testid="epic-boards-sidebar"]'
)
end
context
'labels'
do
it
'adds a single label'
do
click_card
(
card
)
page
.
within
(
'.labels'
)
do
click_button
'Edit'
wait_for_requests
click_link
bug
.
title
find
(
'[data-testid="close-icon"]'
).
click
wait_for_requests
page
.
within
(
'.value'
)
do
expect
(
page
).
to
have_selector
(
'.gl-label-text'
,
count:
1
)
expect
(
page
).
to
have_content
(
bug
.
title
)
end
end
expect
(
card
).
to
have_selector
(
'.gl-label'
,
count:
1
)
expect
(
card
).
to
have_content
(
bug
.
title
)
end
end
end
ee/spec/frontend/boards/components/board_content_sidebar_spec.js
View file @
d213000c
...
...
@@ -20,7 +20,7 @@ describe('ee/BoardContentSidebar', () => {
issuableType
:
issuableTypes
.
issue
,
},
getters
:
{
active
Issue
:
()
=>
{
active
BoardItem
:
()
=>
{
return
{
...
mockIssue
,
epic
:
null
};
},
projectPathForActiveIssue
:
()
=>
mockIssueProjectPath
,
...
...
ee/spec/frontend/boards/components/epic_board_content_sidebar_spec.js
0 → 100644
View file @
d213000c
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
EpicBoardContentSidebar
from
'
ee_component/boards/components/epic_board_content_sidebar.vue
'
;
import
{
stubComponent
}
from
'
helpers/stub_component
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
mockEpic
}
from
'
../mock_data
'
;
describe
(
'
EpicBoardContentSidebar
'
,
()
=>
{
let
wrapper
;
let
store
;
const
createStore
=
({
mockGetters
=
{},
mockActions
=
{}
}
=
{})
=>
{
store
=
new
Vuex
.
Store
({
state
:
{
sidebarType
:
ISSUABLE
,
boardItems
:
{
[
mockEpic
.
id
]:
mockEpic
},
activeId
:
mockEpic
.
id
,
issuableType
:
'
epic
'
,
},
getters
:
{
activeBoardItem
:
()
=>
{
return
mockEpic
;
},
isSidebarOpen
:
()
=>
true
,
...
mockGetters
,
},
actions
:
mockActions
,
});
};
const
createComponent
=
()
=>
{
wrapper
=
shallowMount
(
EpicBoardContentSidebar
,
{
provide
:
{
canUpdate
:
true
,
rootPath
:
'
/
'
,
groupId
:
1
,
},
store
,
stubs
:
{
GlDrawer
:
stubComponent
(
GlDrawer
,
{
template
:
'
<div><slot name="header"></slot><slot></slot></div>
'
,
}),
},
});
};
beforeEach
(()
=>
{
createStore
();
createComponent
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
confirms we render GlDrawer
'
,
()
=>
{
expect
(
wrapper
.
find
(
GlDrawer
).
exists
()).
toBe
(
true
);
});
it
(
'
does not render GlDrawer when isSidebarOpen is false
'
,
()
=>
{
createStore
({
mockGetters
:
{
isSidebarOpen
:
()
=>
false
}
});
createComponent
();
expect
(
wrapper
.
find
(
GlDrawer
).
exists
()).
toBe
(
false
);
});
it
(
'
applies an open attribute
'
,
()
=>
{
expect
(
wrapper
.
find
(
GlDrawer
).
props
(
'
open
'
)).
toBe
(
true
);
});
it
(
'
renders BoardSidebarLabelsSelect
'
,
()
=>
{
expect
(
wrapper
.
find
(
BoardSidebarLabelsSelect
).
exists
()).
toBe
(
true
);
});
describe
(
'
when we emit close
'
,
()
=>
{
let
toggleBoardItem
;
beforeEach
(()
=>
{
toggleBoardItem
=
jest
.
fn
();
createStore
({
mockActions
:
{
toggleBoardItem
}
});
createComponent
();
});
it
(
'
calls toggleBoardItem with correct parameters
'
,
async
()
=>
{
wrapper
.
find
(
GlDrawer
).
vm
.
$emit
(
'
close
'
);
expect
(
toggleBoardItem
).
toHaveBeenCalledTimes
(
1
);
expect
(
toggleBoardItem
).
toHaveBeenCalledWith
(
expect
.
any
(
Object
),
{
boardItem
:
mockEpic
,
sidebarType
:
ISSUABLE
,
});
});
});
});
ee/spec/frontend/boards/mock_data.js
View file @
d213000c
...
...
@@ -115,7 +115,7 @@ export const mockIterations = [
},
];
const
labels
=
[
export
const
labels
=
[
{
id
:
'
gid://gitlab/GroupLabel/5
'
,
title
:
'
Cosync
'
,
...
...
ee/spec/frontend/boards/stores/actions_spec.js
View file @
d213000c
...
...
@@ -15,6 +15,7 @@ import * as typesCE from '~/boards/stores/mutation_types';
import
*
as
commonUtils
from
'
~/lib/utils/common_utils
'
;
import
{
mergeUrlParams
,
removeParams
}
from
'
~/lib/utils/url_utility
'
;
import
{
labels
,
mockLists
,
mockIssue
,
mockIssue2
,
...
...
@@ -578,7 +579,7 @@ describe('fetchEpicForActiveIssue', () => {
};
describe
(
"
when active issue doesn't have an assigned epic
"
,
()
=>
{
const
getters
=
{
active
Issue
:
{
...
mockIssue
,
epic
:
null
}
};
const
getters
=
{
active
BoardItem
:
{
...
mockIssue
,
epic
:
null
}
};
it
(
'
should not fetch any epic
'
,
async
()
=>
{
await
testAction
(
actions
.
fetchEpicForActiveIssue
,
undefined
,
{
...
getters
},
[],
[]);
...
...
@@ -586,7 +587,7 @@ describe('fetchEpicForActiveIssue', () => {
});
describe
(
'
when the assigned epic for active issue is found in state.epicsCacheById
'
,
()
=>
{
const
getters
=
{
active
Issue
:
{
...
mockIssue
,
epic
:
assignedEpic
}
};
const
getters
=
{
active
BoardItem
:
{
...
mockIssue
,
epic
:
assignedEpic
}
};
const
state
=
{
epicsCacheById
:
{
[
assignedEpic
.
id
]:
assignedEpic
}
};
it
(
'
should not fetch any epic
'
,
async
()
=>
{
...
...
@@ -601,7 +602,7 @@ describe('fetchEpicForActiveIssue', () => {
});
describe
(
'
when fetching fails
'
,
()
=>
{
const
getters
=
{
active
Issue
:
{
...
mockIssue
,
epic
:
assignedEpic
}
};
const
getters
=
{
active
BoardItem
:
{
...
mockIssue
,
epic
:
assignedEpic
}
};
const
state
=
{
epicsCacheById
:
{}
};
it
(
'
should not commit UPDATE_CACHED_EPICS mutation and should throw an error
'
,
()
=>
{
...
...
@@ -630,7 +631,7 @@ describe('fetchEpicForActiveIssue', () => {
});
describe
(
"
when the assigned epic for active issue isn't found in state.epicsCacheById
"
,
()
=>
{
const
getters
=
{
active
Issue
:
{
...
mockIssue
,
epic
:
assignedEpic
}
};
const
getters
=
{
active
BoardItem
:
{
...
mockIssue
,
epic
:
assignedEpic
}
};
const
state
=
{
epicsCacheById
:
{}
};
it
(
'
should commit mutation SET_EPIC_FETCH_IN_PROGRESS before and after committing mutation UPDATE_CACHED_EPICS
'
,
async
()
=>
{
...
...
@@ -664,7 +665,7 @@ describe('setActiveIssueEpic', () => {
const
state
=
{
epics
:
[{
id
:
'
gid://gitlab/Epic/422
'
,
iid
:
99
,
title
:
'
existing epic
'
}],
};
const
getters
=
{
active
Issue
:
{
...
mockIssue
,
projectPath
:
'
h/b
'
}
};
const
getters
=
{
active
BoardItem
:
{
...
mockIssue
,
projectPath
:
'
h/b
'
}
};
const
epicWithData
=
{
id
:
'
gid://gitlab/Epic/42
'
,
iid
:
1
,
...
...
@@ -672,7 +673,7 @@ describe('setActiveIssueEpic', () => {
};
describe
(
'
when the updated issue has an assigned epic
'
,
()
=>
{
it
(
'
should commit mutation RECEIVE_EPICS_SUCCESS, UPDATE_CACHED_EPICS and UPDATE_
ISSUE
_BY_ID on success
'
,
async
()
=>
{
it
(
'
should commit mutation RECEIVE_EPICS_SUCCESS, UPDATE_CACHED_EPICS and UPDATE_
BOARD_ITEM
_BY_ID on success
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
issueSetEpic
:
{
issue
:
{
epic
:
epicWithData
}
}
}
});
...
...
@@ -695,9 +696,9 @@ describe('setActiveIssueEpic', () => {
payload
:
[
epicWithData
],
},
{
type
:
typesCE
.
UPDATE_
ISSUE
_BY_ID
,
type
:
typesCE
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
:
{
i
ssue
Id
:
mockIssue
.
id
,
i
tem
Id
:
mockIssue
.
id
,
prop
:
'
epic
'
,
value
:
{
id
:
epicWithData
.
id
,
iid
:
epicWithData
.
iid
},
},
...
...
@@ -713,7 +714,7 @@ describe('setActiveIssueEpic', () => {
});
describe
(
'
when the updated issue does not have an epic (unassigned)
'
,
()
=>
{
it
(
'
should only commit UPDATE_
ISSUE
_BY_ID on success
'
,
async
()
=>
{
it
(
'
should only commit UPDATE_
BOARD_ITEM
_BY_ID on success
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
issueSetEpic
:
{
issue
:
{
epic
:
null
}
}
}
});
...
...
@@ -728,8 +729,8 @@ describe('setActiveIssueEpic', () => {
payload
:
true
,
},
{
type
:
typesCE
.
UPDATE_
ISSUE
_BY_ID
,
payload
:
{
i
ssue
Id
:
mockIssue
.
id
,
prop
:
'
epic
'
,
value
:
null
},
type
:
typesCE
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
:
{
i
tem
Id
:
mockIssue
.
id
,
prop
:
'
epic
'
,
value
:
null
},
},
{
type
:
types
.
SET_EPIC_FETCH_IN_PROGRESS
,
...
...
@@ -752,7 +753,7 @@ describe('setActiveIssueEpic', () => {
describe
(
'
setActiveIssueWeight
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockIssue
.
id
]:
mockIssue
}
};
const
getters
=
{
active
Issue
:
mockIssue
};
const
getters
=
{
active
BoardItem
:
mockIssue
};
const
testWeight
=
mockIssue
.
weight
+
1
;
const
input
=
{
weight
:
testWeight
,
...
...
@@ -772,7 +773,7 @@ describe('setActiveIssueWeight', () => {
});
const
payload
=
{
i
ssueId
:
getters
.
activeIssue
.
id
,
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
weight
'
,
value
:
testWeight
,
};
...
...
@@ -783,7 +784,7 @@ describe('setActiveIssueWeight', () => {
{
...
state
,
...
getters
},
[
{
type
:
typesCE
.
UPDATE_
ISSUE
_BY_ID
,
type
:
typesCE
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
,
},
],
...
...
@@ -1367,3 +1368,48 @@ describe('fetchAssignees', () => {
});
});
});
describe
(
'
setActiveEpicLabels
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockEpic
.
id
]:
mockEpic
}
};
const
getters
=
{
activeBoardItem
:
mockEpic
};
const
testLabelIds
=
labels
.
map
((
label
)
=>
label
.
id
);
const
input
=
{
addLabelIds
:
testLabelIds
,
removeLabelIds
:
[],
groupPath
:
'
h/b
'
,
};
it
(
'
should assign labels on success
'
,
(
done
)
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
updateEpic
:
{
epic
:
{
labels
:
{
nodes
:
labels
}
}
}
}
});
const
payload
=
{
itemId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
labels
,
};
testAction
(
actions
.
setActiveEpicLabels
,
input
,
{
...
state
,
...
getters
},
[
{
type
:
typesCE
.
UPDATE_BOARD_ITEM_BY_ID
,
payload
,
},
],
[],
done
,
);
});
it
(
'
throws error if fails
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
)
.
mockResolvedValue
({
data
:
{
updateEpic
:
{
errors
:
[
'
failed mutation
'
]
}
}
});
await
expect
(
actions
.
setActiveEpicLabels
({
getters
},
input
)).
rejects
.
toThrow
(
Error
);
});
});
locale/gitlab.pot
View file @
d213000c
...
...
@@ -12108,6 +12108,9 @@ msgstr ""
msgid "Epic cannot be found."
msgstr ""
msgid "Epic details"
msgstr ""
msgid "Epic events"
msgstr ""
...
...
spec/features/boards/new_issue_spec.rb
View file @
d213000c
...
...
@@ -90,7 +90,7 @@ RSpec.describe 'Issue Boards new issue', :js do
wait_for_requests
expect
(
page
).
to
have_selector
(
'
.issue-boards-sidebar
'
)
expect
(
page
).
to
have_selector
(
'
[data-testid="issue-boards-sidebar"]
'
)
end
it
'successfuly loads labels to be added to newly created issue'
do
...
...
@@ -109,7 +109,7 @@ RSpec.describe 'Issue Boards new issue', :js do
find
(
'.board-card'
).
click
end
page
.
within
(
first
(
'
.issue-boards-sidebar
'
))
do
page
.
within
(
first
(
'
[data-testid="issue-boards-sidebar"]
'
))
do
find
(
'.labels [data-testid="edit-button"]'
).
click
wait_for_requests
...
...
spec/frontend/boards/components/board_content_sidebar_spec.js
View file @
d213000c
...
...
@@ -24,7 +24,7 @@ describe('BoardContentSidebar', () => {
issuableType
:
'
issue
'
,
},
getters
:
{
active
Issue
:
()
=>
{
active
BoardItem
:
()
=>
{
return
{
...
mockIssue
,
epic
:
null
};
},
groupPathForActiveIssue
:
()
=>
mockIssueGroupPath
,
...
...
spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
View file @
d213000c
...
...
@@ -64,7 +64,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach
(
async
()
=>
{
createWrapper
();
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
Issue
Labels
'
).
mockImplementation
(()
=>
TEST_LABELS
);
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
BoardItem
Labels
'
).
mockImplementation
(()
=>
TEST_LABELS
);
findLabelsSelect
().
vm
.
$emit
(
'
updateSelectedLabels
'
,
TEST_LABELS_PAYLOAD
);
store
.
state
.
boardItems
[
TEST_ISSUE
.
id
].
labels
=
TEST_LABELS
;
await
wrapper
.
vm
.
$nextTick
();
...
...
@@ -76,7 +76,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
});
it
(
'
commits change to the server
'
,
()
=>
{
expect
(
wrapper
.
vm
.
setActive
Issue
Labels
).
toHaveBeenCalledWith
({
expect
(
wrapper
.
vm
.
setActive
BoardItem
Labels
).
toHaveBeenCalledWith
({
addLabelIds
:
TEST_LABELS
.
map
((
label
)
=>
label
.
id
),
projectPath
:
'
gitlab-org/test-subgroup/gitlab-test
'
,
removeLabelIds
:
[],
...
...
@@ -94,13 +94,13 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach
(
async
()
=>
{
createWrapper
({
labels
:
TEST_LABELS
});
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
Issue
Labels
'
).
mockImplementation
(()
=>
expectedLabels
);
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
BoardItem
Labels
'
).
mockImplementation
(()
=>
expectedLabels
);
findLabelsSelect
().
vm
.
$emit
(
'
updateSelectedLabels
'
,
testLabelsPayload
);
await
wrapper
.
vm
.
$nextTick
();
});
it
(
'
commits change to the server
'
,
()
=>
{
expect
(
wrapper
.
vm
.
setActive
Issue
Labels
).
toHaveBeenCalledWith
({
expect
(
wrapper
.
vm
.
setActive
BoardItem
Labels
).
toHaveBeenCalledWith
({
addLabelIds
:
[
5
,
7
],
removeLabelIds
:
[
6
],
projectPath
:
'
gitlab-org/test-subgroup/gitlab-test
'
,
...
...
@@ -114,13 +114,13 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach
(
async
()
=>
{
createWrapper
({
labels
:
[
testLabel
]
});
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
Issue
Labels
'
).
mockImplementation
(()
=>
{});
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
BoardItem
Labels
'
).
mockImplementation
(()
=>
{});
});
it
(
'
commits change to the server
'
,
()
=>
{
wrapper
.
find
(
GlLabel
).
vm
.
$emit
(
'
close
'
,
testLabel
);
expect
(
wrapper
.
vm
.
setActive
Issue
Labels
).
toHaveBeenCalledWith
({
expect
(
wrapper
.
vm
.
setActive
BoardItem
Labels
).
toHaveBeenCalledWith
({
removeLabelIds
:
[
getIdFromGraphQLId
(
testLabel
.
id
)],
projectPath
:
'
gitlab-org/test-subgroup/gitlab-test
'
,
});
...
...
@@ -131,7 +131,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach
(
async
()
=>
{
createWrapper
({
labels
:
TEST_LABELS
});
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
Issue
Labels
'
).
mockImplementation
(()
=>
{
jest
.
spyOn
(
wrapper
.
vm
,
'
setActive
BoardItem
Labels
'
).
mockImplementation
(()
=>
{
throw
new
Error
([
'
failed mutation
'
]);
});
findLabelsSelect
().
vm
.
$emit
(
'
updateSelectedLabels
'
,
[{
id
:
'
?
'
}]);
...
...
spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
View file @
d213000c
...
...
@@ -20,10 +20,10 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
const
findToggle
=
()
=>
wrapper
.
find
(
GlToggle
);
const
findGlLoadingIcon
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
const
createComponent
=
(
active
Issue
=
{
...
mockActiveIssue
})
=>
{
const
createComponent
=
(
active
BoardItem
=
{
...
mockActiveIssue
})
=>
{
store
=
createStore
();
store
.
state
.
boardItems
=
{
[
active
Issue
.
id
]:
activeIssue
};
store
.
state
.
activeId
=
active
Issue
.
id
;
store
.
state
.
boardItems
=
{
[
active
BoardItem
.
id
]:
activeBoardItem
};
store
.
state
.
activeId
=
active
BoardItem
.
id
;
wrapper
=
mount
(
BoardSidebarSubscription
,
{
localVue
,
...
...
@@ -91,8 +91,8 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
describe
(
'
Board sidebar subscription component `behavior`
'
,
()
=>
{
const
mockSetActiveIssueSubscribed
=
(
subscribedState
)
=>
{
jest
.
spyOn
(
wrapper
.
vm
,
'
setActiveIssueSubscribed
'
).
mockImplementation
(
async
()
=>
{
store
.
commit
(
types
.
UPDATE_
ISSUE
_BY_ID
,
{
i
ssue
Id
:
mockActiveIssue
.
id
,
store
.
commit
(
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
{
i
tem
Id
:
mockActiveIssue
.
id
,
prop
:
'
subscribed
'
,
value
:
subscribedState
,
});
...
...
spec/frontend/boards/stores/actions_spec.js
View file @
d213000c
...
...
@@ -802,11 +802,11 @@ describe('setAssignees', () => {
testAction
(
actions
.
setAssignees
,
[
node
],
{
active
Issue
:
{
iid
,
referencePath
:
refPath
},
commit
:
()
=>
{}
},
{
active
BoardItem
:
{
iid
,
referencePath
:
refPath
},
commit
:
()
=>
{}
},
[
{
type
:
'
UPDATE_
ISSUE
_BY_ID
'
,
payload
:
{
prop
:
'
assignees
'
,
i
ssue
Id
:
undefined
,
value
:
[
node
]
},
type
:
'
UPDATE_
BOARD_ITEM
_BY_ID
'
,
payload
:
{
prop
:
'
assignees
'
,
i
tem
Id
:
undefined
,
value
:
[
node
]
},
},
],
[],
...
...
@@ -949,7 +949,7 @@ describe('addListIssue', () => {
describe
(
'
setActiveIssueLabels
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockIssue
.
id
]:
mockIssue
}
};
const
getters
=
{
active
Issue
:
mockIssue
};
const
getters
=
{
active
BoardItem
:
mockIssue
};
const
testLabelIds
=
labels
.
map
((
label
)
=>
label
.
id
);
const
input
=
{
addLabelIds
:
testLabelIds
,
...
...
@@ -963,7 +963,7 @@ describe('setActiveIssueLabels', () => {
.
mockResolvedValue
({
data
:
{
updateIssue
:
{
issue
:
{
labels
:
{
nodes
:
labels
}
}
}
}
});
const
payload
=
{
i
ssueId
:
getters
.
activeIssue
.
id
,
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
labels
'
,
value
:
labels
,
};
...
...
@@ -974,7 +974,7 @@ describe('setActiveIssueLabels', () => {
{
...
state
,
...
getters
},
[
{
type
:
types
.
UPDATE_
ISSUE
_BY_ID
,
type
:
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
,
},
],
...
...
@@ -994,7 +994,7 @@ describe('setActiveIssueLabels', () => {
describe
(
'
setActiveIssueDueDate
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockIssue
.
id
]:
mockIssue
}
};
const
getters
=
{
active
Issue
:
mockIssue
};
const
getters
=
{
active
BoardItem
:
mockIssue
};
const
testDueDate
=
'
2020-02-20
'
;
const
input
=
{
dueDate
:
testDueDate
,
...
...
@@ -1014,7 +1014,7 @@ describe('setActiveIssueDueDate', () => {
});
const
payload
=
{
i
ssueId
:
getters
.
activeIssue
.
id
,
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
dueDate
'
,
value
:
testDueDate
,
};
...
...
@@ -1025,7 +1025,7 @@ describe('setActiveIssueDueDate', () => {
{
...
state
,
...
getters
},
[
{
type
:
types
.
UPDATE_
ISSUE
_BY_ID
,
type
:
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
,
},
],
...
...
@@ -1045,7 +1045,7 @@ describe('setActiveIssueDueDate', () => {
describe
(
'
setActiveIssueSubscribed
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockActiveIssue
.
id
]:
mockActiveIssue
}
};
const
getters
=
{
active
Issue
:
mockActiveIssue
};
const
getters
=
{
active
BoardItem
:
mockActiveIssue
};
const
subscribedState
=
true
;
const
input
=
{
subscribedState
,
...
...
@@ -1065,7 +1065,7 @@ describe('setActiveIssueSubscribed', () => {
});
const
payload
=
{
i
ssueId
:
getters
.
activeIssue
.
id
,
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
subscribed
'
,
value
:
subscribedState
,
};
...
...
@@ -1076,7 +1076,7 @@ describe('setActiveIssueSubscribed', () => {
{
...
state
,
...
getters
},
[
{
type
:
types
.
UPDATE_
ISSUE
_BY_ID
,
type
:
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
,
},
],
...
...
@@ -1096,7 +1096,7 @@ describe('setActiveIssueSubscribed', () => {
describe
(
'
setActiveIssueMilestone
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockIssue
.
id
]:
mockIssue
}
};
const
getters
=
{
active
Issue
:
mockIssue
};
const
getters
=
{
active
BoardItem
:
mockIssue
};
const
testMilestone
=
{
...
mockMilestone
,
id
:
'
gid://gitlab/Milestone/1
'
,
...
...
@@ -1119,7 +1119,7 @@ describe('setActiveIssueMilestone', () => {
});
const
payload
=
{
i
ssueId
:
getters
.
activeIssue
.
id
,
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
milestone
'
,
value
:
testMilestone
,
};
...
...
@@ -1130,7 +1130,7 @@ describe('setActiveIssueMilestone', () => {
{
...
state
,
...
getters
},
[
{
type
:
types
.
UPDATE_
ISSUE
_BY_ID
,
type
:
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
,
},
],
...
...
@@ -1150,7 +1150,7 @@ describe('setActiveIssueMilestone', () => {
describe
(
'
setActiveIssueTitle
'
,
()
=>
{
const
state
=
{
boardItems
:
{
[
mockIssue
.
id
]:
mockIssue
}
};
const
getters
=
{
active
Issue
:
mockIssue
};
const
getters
=
{
active
BoardItem
:
mockIssue
};
const
testTitle
=
'
Test Title
'
;
const
input
=
{
title
:
testTitle
,
...
...
@@ -1170,7 +1170,7 @@ describe('setActiveIssueTitle', () => {
});
const
payload
=
{
i
ssueId
:
getters
.
activeIssue
.
id
,
i
temId
:
getters
.
activeBoardItem
.
id
,
prop
:
'
title
'
,
value
:
testTitle
,
};
...
...
@@ -1181,7 +1181,7 @@ describe('setActiveIssueTitle', () => {
{
...
state
,
...
getters
},
[
{
type
:
types
.
UPDATE_
ISSUE
_BY_ID
,
type
:
types
.
UPDATE_
BOARD_ITEM
_BY_ID
,
payload
,
},
],
...
...
@@ -1325,7 +1325,7 @@ describe('toggleBoardItemMultiSelection', () => {
testAction
(
actions
.
toggleBoardItemMultiSelection
,
boardItem2
,
{
activeId
:
mockActiveIssue
.
id
,
active
Issue
:
mockActiveIssue
,
selectedBoardItems
:
[]
},
{
activeId
:
mockActiveIssue
.
id
,
active
BoardItem
:
mockActiveIssue
,
selectedBoardItems
:
[]
},
[
{
type
:
types
.
ADD_BOARD_ITEM_TO_SELECTION
,
...
...
spec/frontend/boards/stores/getters_spec.js
View file @
d213000c
...
...
@@ -88,7 +88,7 @@ describe('Boards - Getters', () => {
});
});
describe('active
Issue
', () => {
describe('active
BoardItem
', () => {
it.each`
id
|
expected
$
{
'
1
'
}
|
${
'
issue
'
}
...
...
@@ -96,7 +96,7 @@ describe('Boards - Getters', () => {
`('returns $expected when $id is passed to state', ({ id, expected }) => {
const state = { boardItems: { 1: 'issue' }, activeId: id };
expect(getters.active
Issue
(state)).toEqual(expected);
expect(getters.active
BoardItem
(state)).toEqual(expected);
});
});
...
...
@@ -105,14 +105,14 @@ describe('Boards - Getters', () => {
const mockActiveIssue = {
referencePath: 'gitlab-org/gitlab-test#1',
};
expect(getters.groupPathForActiveIssue({}, { active
Issue
: mockActiveIssue })).toEqual(
expect(getters.groupPathForActiveIssue({}, { active
BoardItem
: mockActiveIssue })).toEqual(
'gitlab-org',
);
});
it('returns empty string as group path when active issue is an empty object', () => {
const mockActiveIssue = {};
expect(getters.groupPathForActiveIssue({}, { active
Issue
: mockActiveIssue })).toEqual('');
expect(getters.groupPathForActiveIssue({}, { active
BoardItem
: mockActiveIssue })).toEqual('');
});
});
...
...
@@ -121,14 +121,16 @@ describe('Boards - Getters', () => {
const mockActiveIssue = {
referencePath: 'gitlab-org/gitlab-test#1',
};
expect(getters.projectPathForActiveIssue({}, { active
Issue
: mockActiveIssue })).toEqual(
expect(getters.projectPathForActiveIssue({}, { active
BoardItem
: mockActiveIssue })).toEqual(
'gitlab-org/gitlab-test',
);
});
it('returns empty string as project path when active issue is an empty object', () => {
const mockActiveIssue = {};
expect(getters.projectPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual('');
expect(getters.projectPathForActiveIssue({}, { activeBoardItem: mockActiveIssue })).toEqual(
'',
);
});
});
...
...
spec/frontend/boards/stores/mutations_spec.js
View file @
d213000c
...
...
@@ -335,7 +335,7 @@ describe('Board Store Mutations', () => {
expectNotImplemented
(
mutations
.
REQUEST_ADD_ISSUE
);
});
describe
(
'
UPDATE_
ISSUE
_BY_ID
'
,
()
=>
{
describe
(
'
UPDATE_
BOARD_ITEM
_BY_ID
'
,
()
=>
{
const
issueId
=
'
1
'
;
const
prop
=
'
id
'
;
const
value
=
'
2
'
;
...
...
@@ -353,8 +353,8 @@ describe('Board Store Mutations', () => {
describe
(
'
when the issue is in state
'
,
()
=>
{
it
(
'
updates the property of the correct issue
'
,
()
=>
{
mutations
.
UPDATE_
ISSUE
_BY_ID
(
state
,
{
issueId
,
mutations
.
UPDATE_
BOARD_ITEM
_BY_ID
(
state
,
{
i
temId
:
i
ssueId
,
prop
,
value
,
});
...
...
@@ -366,8 +366,8 @@ describe('Board Store Mutations', () => {
describe
(
'
when the issue is not in state
'
,
()
=>
{
it
(
'
throws an error
'
,
()
=>
{
expect
(()
=>
{
mutations
.
UPDATE_
ISSUE
_BY_ID
(
state
,
{
i
ssue
Id
:
'
3
'
,
mutations
.
UPDATE_
BOARD_ITEM
_BY_ID
(
state
,
{
i
tem
Id
:
'
3
'
,
prop
,
value
,
});
...
...
spec/support/shared_examples/features/sidebar_shared_examples.rb
View file @
d213000c
...
...
@@ -8,19 +8,19 @@ RSpec.shared_examples 'issue boards sidebar' do
end
it
'shows sidebar when clicking issue'
do
expect
(
page
).
to
have_selector
(
'
.issue-boards-sidebar
'
)
expect
(
page
).
to
have_selector
(
'
[data-testid="issue-boards-sidebar"]
'
)
end
it
'closes sidebar when clicking issue'
do
expect
(
page
).
to
have_selector
(
'
.issue-boards-sidebar
'
)
expect
(
page
).
to
have_selector
(
'
[data-testid="issue-boards-sidebar"]
'
)
first_card
.
click
expect
(
page
).
not_to
have_selector
(
'
.issue-boards-sidebar
'
)
expect
(
page
).
not_to
have_selector
(
'
[data-testid="issue-boards-sidebar"]
'
)
end
it
'shows issue details when sidebar is open'
,
:aggregate_failures
do
page
.
within
(
'
.issue-boards-sidebar
'
)
do
page
.
within
(
'
[data-testid="issue-boards-sidebar"]
'
)
do
expect
(
page
).
to
have_content
(
issue
.
title
)
expect
(
page
).
to
have_content
(
issue
.
to_reference
)
end
...
...
@@ -28,7 +28,7 @@ RSpec.shared_examples 'issue boards sidebar' do
context
'when clicking close button'
do
before
do
find
(
"[data-testid='sidebar-drawer'] .gl-drawer-close-button"
).
click
find
(
'[data-testid="issue-boards-sidebar"] .gl-drawer-close-button'
).
click
end
it
'unhighlights the active issue card'
do
...
...
@@ -37,7 +37,7 @@ RSpec.shared_examples 'issue boards sidebar' do
end
it
'closes sidebar when clicking close button'
do
expect
(
page
).
not_to
have_selector
(
'
.issue-boards-sidebar
'
)
expect
(
page
).
not_to
have_selector
(
'
[data-testid="issue-boards-sidebar"]
'
)
end
end
...
...
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