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
7ef0808f
Commit
7ef0808f
authored
Nov 06, 2020
by
Scott Stern
Committed by
Simon Knox
Nov 06, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add assignee dropdown to Epic Boards sidebar
parent
1c777ad3
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
498 additions
and
26 deletions
+498
-26
app/assets/javascripts/boards/components/board_assignee_dropdown.vue
...javascripts/boards/components/board_assignee_dropdown.vue
+144
-0
app/assets/javascripts/boards/components/issue_card_inner.vue
...assets/javascripts/boards/components/issue_card_inner.vue
+1
-1
app/assets/javascripts/boards/stores/actions.js
app/assets/javascripts/boards/stores/actions.js
+20
-0
app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue
...ascripts/sidebar/components/assignees/assignee_avatar.vue
+3
-1
app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
...ripts/sidebar/components/assignees/issuable_assignees.vue
+0
-1
app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
...onents/sidebar/queries/getIssueParticipants.query.graphql
+13
-0
app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
...mponents/sidebar/queries/updateAssignees.mutation.graphql
+17
-0
changelogs/unreleased/ss-add-assignee-dropdown.yml
changelogs/unreleased/ss-add-assignee-dropdown.yml
+5
-0
ee/app/assets/javascripts/boards/components/board_content_sidebar.vue
...s/javascripts/boards/components/board_content_sidebar.vue
+3
-3
ee/spec/frontend/boards/components/board_content_sidebar_spec.js
.../frontend/boards/components/board_content_sidebar_spec.js
+3
-2
spec/frontend/boards/components/board_assignee_dropdown_spec.js
...rontend/boards/components/board_assignee_dropdown_spec.js
+229
-0
spec/frontend/boards/mock_data.js
spec/frontend/boards/mock_data.js
+17
-0
spec/frontend/boards/stores/actions_spec.js
spec/frontend/boards/stores/actions_spec.js
+43
-0
spec/frontend/sidebar/issuable_assignees_spec.js
spec/frontend/sidebar/issuable_assignees_spec.js
+0
-18
No files found.
app/assets/javascripts/boards/components/board_assignee_dropdown.vue
0 → 100644
View file @
7ef0808f
<
script
>
import
{
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
{
GlDropdownItem
,
GlDropdownDivider
,
GlAvatarLabeled
,
GlAvatarLink
}
from
'
@gitlab/ui
'
;
import
{
__
,
n__
}
from
'
~/locale
'
;
import
IssuableAssignees
from
'
~/sidebar/components/assignees/issuable_assignees.vue
'
;
import
BoardEditableItem
from
'
~/boards/components/sidebar/board_editable_item.vue
'
;
import
AssigneesDropdown
from
'
~/vue_shared/components/sidebar/assignees_dropdown.vue
'
;
import
getIssueParticipants
from
'
~/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
'
;
export
default
{
i18n
:
{
unassigned
:
__
(
'
Unassigned
'
),
assignee
:
__
(
'
Assignee
'
),
assignees
:
__
(
'
Assignees
'
),
assignTo
:
__
(
'
Assign to
'
),
},
components
:
{
BoardEditableItem
,
IssuableAssignees
,
AssigneesDropdown
,
GlDropdownItem
,
GlDropdownDivider
,
GlAvatarLabeled
,
GlAvatarLink
,
},
data
()
{
return
{
participants
:
[],
selected
:
this
.
$store
.
getters
.
getActiveIssue
.
assignees
,
};
},
apollo
:
{
participants
:
{
query
:
getIssueParticipants
,
variables
()
{
return
{
id
:
`gid://gitlab/Issue/
${
this
.
getActiveIssue
.
iid
}
`
,
};
},
update
(
data
)
{
return
data
.
issue
?.
participants
?.
nodes
||
[];
},
},
},
computed
:
{
...
mapGetters
([
'
getActiveIssue
'
]),
assigneeText
()
{
return
n__
(
'
Assignee
'
,
'
%d Assignees
'
,
this
.
selected
.
length
);
},
unSelectedFiltered
()
{
return
this
.
participants
.
filter
(({
username
})
=>
{
return
!
this
.
selectedUserNames
.
includes
(
username
);
});
},
selectedIsEmpty
()
{
return
this
.
selected
.
length
===
0
;
},
selectedUserNames
()
{
return
this
.
selected
.
map
(({
username
})
=>
username
);
},
},
methods
:
{
...
mapActions
([
'
setAssignees
'
]),
clearSelected
()
{
this
.
selected
=
[];
},
selectAssignee
(
name
)
{
if
(
name
===
undefined
)
{
this
.
clearSelected
();
return
;
}
this
.
selected
=
this
.
selected
.
concat
(
name
);
},
unselect
(
name
)
{
this
.
selected
=
this
.
selected
.
filter
(
user
=>
user
.
username
!==
name
);
},
saveAssignees
()
{
this
.
setAssignees
(
this
.
selectedUserNames
);
},
isChecked
(
id
)
{
return
this
.
selectedUserNames
.
includes
(
id
);
},
},
};
</
script
>
<
template
>
<board-editable-item
:title=
"assigneeText"
@
close=
"saveAssignees"
>
<template
#collapsed
>
<issuable-assignees
:users=
"getActiveIssue.assignees"
/>
</
template
>
<
template
#default
>
<assignees-dropdown
class=
"w-100"
:text=
"$options.i18n.assignees"
:header-text=
"$options.i18n.assignTo"
>
<template
#items
>
<gl-dropdown-item
:is-checked=
"selectedIsEmpty"
data-testid=
"unassign"
class=
"mt-2"
@
click=
"selectAssignee()"
>
{{
$options
.
i18n
.
unassigned
}}
</gl-dropdown-item
>
<gl-dropdown-divider
data-testid=
"unassign-divider"
/>
<gl-dropdown-item
v-for=
"item in selected"
:key=
"item.id"
:is-checked=
"isChecked(item.username)"
@
click=
"unselect(item.username)"
>
<gl-avatar-link>
<gl-avatar-labeled
:size=
"32"
:label=
"item.name"
:sub-label=
"item.username"
:src=
"item.avatarUrl || item.avatar"
/>
</gl-avatar-link>
</gl-dropdown-item>
<gl-dropdown-divider
v-if=
"!selectedIsEmpty"
data-testid=
"selected-user-divider"
/>
<gl-dropdown-item
v-for=
"unselectedUser in unSelectedFiltered"
:key=
"unselectedUser.id"
:data-testid=
"`item_$
{unselectedUser.name}`"
@click="selectAssignee(unselectedUser)"
>
<gl-avatar-link>
<gl-avatar-labeled
:size=
"32"
:label=
"unselectedUser.name"
:sub-label=
"unselectedUser.username"
:src=
"unselectedUser.avatarUrl || unselectedUser.avatar"
/>
</gl-avatar-link>
</gl-dropdown-item>
</
template
>
</assignees-dropdown>
</template>
</board-editable-item>
</template>
app/assets/javascripts/boards/components/issue_card_inner.vue
View file @
7ef0808f
...
...
@@ -205,7 +205,7 @@ export default {
:key=
"assignee.id"
:link-href=
"assigneeUrl(assignee)"
:img-alt=
"avatarUrlTitle(assignee)"
:img-src=
"assignee.avatar || assignee.avatar_url"
:img-src=
"assignee.avatar
Url || assignee.avatar
|| assignee.avatar_url"
:img-size=
"24"
class=
"js-no-trigger"
tooltip-placement=
"bottom"
...
...
app/assets/javascripts/boards/stores/actions.js
View file @
7ef0808f
...
...
@@ -18,6 +18,7 @@ import boardLabelsQuery from '../queries/board_labels.query.graphql';
import
createBoardListMutation
from
'
../queries/board_list_create.mutation.graphql
'
;
import
updateBoardListMutation
from
'
../queries/board_list_update.mutation.graphql
'
;
import
issueMoveListMutation
from
'
../queries/issue_move_list.mutation.graphql
'
;
import
updateAssignees
from
'
~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
'
;
import
issueSetLabels
from
'
../queries/issue_set_labels.mutation.graphql
'
;
import
issueSetDueDate
from
'
../queries/issue_set_due_date.mutation.graphql
'
;
...
...
@@ -291,6 +292,25 @@ export default {
);
},
setAssignees
:
({
commit
,
getters
},
assigneeUsernames
)
=>
{
return
gqlClient
.
mutate
({
mutation
:
updateAssignees
,
variables
:
{
iid
:
getters
.
getActiveIssue
.
iid
,
projectPath
:
getters
.
getActiveIssue
.
referencePath
.
split
(
'
#
'
)[
0
],
assigneeUsernames
,
},
})
.
then
(({
data
})
=>
{
commit
(
'
UPDATE_ISSUE_BY_ID
'
,
{
issueId
:
getters
.
getActiveIssue
.
id
,
prop
:
'
assignees
'
,
value
:
data
.
issueSetAssignees
.
issue
.
assignees
.
nodes
,
});
});
},
createNewIssue
:
()
=>
{
notImplemented
();
},
...
...
app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue
View file @
7ef0808f
...
...
@@ -22,7 +22,9 @@ export default {
return
sprintf
(
__
(
"
%{userName}'s avatar
"
),
{
userName
:
this
.
user
.
name
});
},
avatarUrl
()
{
return
this
.
user
.
avatar
||
this
.
user
.
avatar_url
||
gon
.
default_avatar_url
;
return
(
this
.
user
.
avatarUrl
||
this
.
user
.
avatar
||
this
.
user
.
avatar_url
||
gon
.
default_avatar_url
);
},
isMergeRequest
()
{
return
this
.
issuableType
===
'
merge_request
'
;
...
...
app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
View file @
7ef0808f
...
...
@@ -26,7 +26,6 @@ export default {
<
template
>
<div
class=
"gl-display-flex gl-flex-direction-column"
>
<label
data-testid=
"assigneeLabel"
>
{{
assigneesText
}}
</label>
<div
v-if=
"emptyUsers"
data-testid=
"none"
>
<span>
{{
__
(
'
None
'
)
}}
...
...
app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
0 → 100644
View file @
7ef0808f
query
issueParticipants
(
$id
:
IssueID
!)
{
issue
(
id
:
$id
)
{
participants
{
nodes
{
username
name
webUrl
avatarUrl
id
}
}
}
}
app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
0 → 100644
View file @
7ef0808f
mutation
issueSetAssignees
(
$iid
:
String
!,
$assigneeUsernames
:
[
String
!]!,
$projectPath
:
ID
!)
{
issueSetAssignees
(
input
:
{
iid
:
$iid
,
assigneeUsernames
:
$assigneeUsernames
,
projectPath
:
$projectPath
}
)
{
issue
{
assignees
{
nodes
{
username
id
name
webUrl
avatarUrl
}
}
}
}
}
changelogs/unreleased/ss-add-assignee-dropdown.yml
0 → 100644
View file @
7ef0808f
---
title
:
Add assignee dropdown to group issue boards
merge_request
:
44830
author
:
type
:
added
ee/app/assets/javascripts/boards/components/board_content_sidebar.vue
View file @
7ef0808f
...
...
@@ -3,10 +3,10 @@ import { mapState, mapActions, mapGetters } from 'vuex';
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
import
{
contentTop
}
from
'
~/lib/utils/common_utils
'
;
import
IssuableAssignees
from
'
~/sidebar/components/assignees/issuable_assignees.vue
'
;
import
IssuableTitle
from
'
~/boards/components/issuable_title.vue
'
;
import
glFeatureFlagsMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
BoardSidebarEpicSelect
from
'
./sidebar/board_sidebar_epic_select.vue
'
;
import
BoardAssigneeDropdown
from
'
~/boards/components/board_assignee_dropdown.vue
'
;
import
BoardSidebarTimeTracker
from
'
./sidebar/board_sidebar_time_tracker.vue
'
;
import
BoardSidebarWeightInput
from
'
./sidebar/board_sidebar_weight_input.vue
'
;
import
BoardSidebarLabelsSelect
from
'
~/boards/components/sidebar/board_sidebar_labels_select.vue
'
;
...
...
@@ -15,10 +15,10 @@ import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_d
export
default
{
headerHeight
:
`
${
contentTop
()}
px`
,
components
:
{
IssuableAssignees
,
GlDrawer
,
IssuableTitle
,
BoardSidebarEpicSelect
,
BoardAssigneeDropdown
,
BoardSidebarTimeTracker
,
BoardSidebarWeightInput
,
BoardSidebarLabelsSelect
,
...
...
@@ -50,7 +50,7 @@ export default {
</
template
>
<
template
>
<
issuable-assignees
:users=
"getActiveIssue.assignees"
/>
<
board-assignee-dropdown
/>
<board-sidebar-epic-select
/>
<board-sidebar-time-tracker
class=
"swimlanes-sidebar-time-tracker"
/>
<board-sidebar-weight-input
v-if=
"glFeatures.issueWeights"
/>
...
...
ee/spec/frontend/boards/components/board_content_sidebar_spec.js
View file @
7ef0808f
...
...
@@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils';
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
BoardContentSidebar
from
'
ee_component/boards/components/board_content_sidebar.vue
'
;
import
IssuableAssignees
from
'
~/sidebar/components/assignees/issuable_assignees
.vue
'
;
import
BoardAssigneeDropdown
from
'
~/boards/components/board_assignee_dropdown
.vue
'
;
import
IssuableTitle
from
'
~/boards/components/issuable_title.vue
'
;
import
{
createStore
}
from
'
~/boards/stores
'
;
import
{
ISSUABLE
}
from
'
~/boards/constants
'
;
...
...
@@ -14,6 +14,7 @@ describe('ee/BoardContentSidebar', () => {
const
createComponent
=
()
=>
{
wrapper
=
mount
(
BoardContentSidebar
,
{
provide
:
{
canUpdate
:
true
,
rootPath
:
''
,
},
store
,
...
...
@@ -54,7 +55,7 @@ describe('ee/BoardContentSidebar', () => {
});
it
(
'
renders IssuableAssignees
'
,
()
=>
{
expect
(
wrapper
.
find
(
IssuableAssignees
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
BoardAssigneeDropdown
).
exists
()).
toBe
(
true
);
});
describe
(
'
when we emit close
'
,
()
=>
{
...
...
spec/frontend/boards/components/board_assignee_dropdown_spec.js
0 → 100644
View file @
7ef0808f
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
GlDropdownItem
,
GlAvatarLink
,
GlAvatarLabeled
}
from
'
@gitlab/ui
'
;
import
BoardAssigneeDropdown
from
'
~/boards/components/board_assignee_dropdown.vue
'
;
import
IssuableAssignees
from
'
~/sidebar/components/assignees/issuable_assignees.vue
'
;
import
AssigneesDropdown
from
'
~/vue_shared/components/sidebar/assignees_dropdown.vue
'
;
import
BoardEditableItem
from
'
~/boards/components/sidebar/board_editable_item.vue
'
;
import
store
from
'
~/boards/stores
'
;
import
getIssueParticipants
from
'
~/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
'
;
import
{
participants
}
from
'
../mock_data
'
;
describe
(
'
BoardCardAssigneeDropdown
'
,
()
=>
{
let
wrapper
;
const
iid
=
'
111
'
;
const
activeIssueName
=
'
test
'
;
const
anotherIssueName
=
'
hello
'
;
const
createComponent
=
()
=>
{
wrapper
=
mount
(
BoardAssigneeDropdown
,
{
data
()
{
return
{
selected
:
store
.
getters
.
getActiveIssue
.
assignees
,
participants
,
};
},
store
,
provide
:
{
canUpdate
:
true
,
rootPath
:
''
,
},
});
};
const
unassign
=
async
()
=>
{
wrapper
.
find
(
'
[data-testid="unassign"]
'
).
trigger
(
'
click
'
);
await
wrapper
.
vm
.
$nextTick
();
};
const
openDropdown
=
async
()
=>
{
wrapper
.
find
(
'
[data-testid="edit-button"]
'
).
trigger
(
'
click
'
);
await
wrapper
.
vm
.
$nextTick
();
};
const
findByText
=
text
=>
{
return
wrapper
.
findAll
(
GlDropdownItem
).
wrappers
.
find
(
x
=>
x
.
text
().
indexOf
(
text
)
===
0
);
};
beforeEach
(()
=>
{
store
.
state
.
activeId
=
'
1
'
;
store
.
state
.
issues
=
{
'
1
'
:
{
iid
,
assignees
:
[{
username
:
activeIssueName
,
name
:
activeIssueName
,
id
:
activeIssueName
}],
},
};
jest
.
spyOn
(
store
,
'
dispatch
'
).
mockResolvedValue
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
when mounted
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
.
each
`
text
${
anotherIssueName
}
${
activeIssueName
}
`
(
'
finds item with $text
'
,
({
text
})
=>
{
const
item
=
findByText
(
text
);
expect
(
item
.
exists
()).
toBe
(
true
);
});
it
(
'
renders gl-avatar-link in gl-dropdown-item
'
,
()
=>
{
const
item
=
findByText
(
'
hello
'
);
expect
(
item
.
find
(
GlAvatarLink
).
exists
()).
toBe
(
true
);
});
it
(
'
renders gl-avatar-labeled in gl-avatar-link
'
,
()
=>
{
const
item
=
findByText
(
'
hello
'
);
expect
(
item
.
find
(
GlAvatarLink
)
.
find
(
GlAvatarLabeled
)
.
exists
(),
).
toBe
(
true
);
});
});
describe
(
'
when selected users are present
'
,
()
=>
{
it
(
'
renders a divider
'
,
()
=>
{
createComponent
();
expect
(
wrapper
.
find
(
'
[data-testid="selected-user-divider"]
'
).
exists
()).
toBe
(
true
);
});
});
describe
(
'
when collapsed
'
,
()
=>
{
it
(
'
renders IssuableAssignees
'
,
()
=>
{
createComponent
();
expect
(
wrapper
.
find
(
IssuableAssignees
).
isVisible
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
AssigneesDropdown
).
isVisible
()).
toBe
(
false
);
});
});
describe
(
'
when dropdown is open
'
,
()
=>
{
beforeEach
(
async
()
=>
{
createComponent
();
await
openDropdown
();
});
it
(
'
shows assignees dropdown
'
,
async
()
=>
{
expect
(
wrapper
.
find
(
IssuableAssignees
).
isVisible
()).
toBe
(
false
);
expect
(
wrapper
.
find
(
AssigneesDropdown
).
isVisible
()).
toBe
(
true
);
});
it
(
'
shows the issue returned as the activeIssue
'
,
async
()
=>
{
expect
(
findByText
(
activeIssueName
).
props
(
'
isChecked
'
)).
toBe
(
true
);
});
describe
(
'
when "Unassign" is clicked
'
,
()
=>
{
it
(
'
unassigns assignees
'
,
async
()
=>
{
await
unassign
();
expect
(
findByText
(
'
Unassign
'
).
props
(
'
isChecked
'
)).
toBe
(
true
);
});
});
describe
(
'
when an unselected item is clicked
'
,
()
=>
{
beforeEach
(
async
()
=>
{
await
unassign
();
});
it
(
'
assigns assignee in the dropdown
'
,
async
()
=>
{
wrapper
.
find
(
'
[data-testid="item_test"]
'
).
trigger
(
'
click
'
);
await
wrapper
.
vm
.
$nextTick
();
expect
(
findByText
(
activeIssueName
).
props
(
'
isChecked
'
)).
toBe
(
true
);
});
it
(
'
calls setAssignees with username list
'
,
async
()
=>
{
wrapper
.
find
(
'
[data-testid="item_test"]
'
).
trigger
(
'
click
'
);
await
wrapper
.
vm
.
$nextTick
();
document
.
body
.
click
();
await
wrapper
.
vm
.
$nextTick
();
expect
(
store
.
dispatch
).
toHaveBeenCalledWith
(
'
setAssignees
'
,
[
activeIssueName
]);
});
});
describe
(
'
when the user off clicks
'
,
()
=>
{
beforeEach
(
async
()
=>
{
await
unassign
();
document
.
body
.
click
();
await
wrapper
.
vm
.
$nextTick
();
});
it
(
'
calls setAssignees with username list
'
,
async
()
=>
{
expect
(
store
.
dispatch
).
toHaveBeenCalledWith
(
'
setAssignees
'
,
[]);
});
it
(
'
closes the dropdown
'
,
async
()
=>
{
expect
(
wrapper
.
find
(
IssuableAssignees
).
isVisible
()).
toBe
(
true
);
});
});
});
it
(
'
renders divider after unassign
'
,
()
=>
{
createComponent
();
expect
(
wrapper
.
find
(
'
[data-testid="unassign-divider"]
'
).
exists
()).
toBe
(
true
);
});
it
.
each
`
assignees | expected
${[{
id
:
5
,
username
:
''
,
name
:
''
}]}
|
${
'
Assignee
'
}
${[{
id
:
6
,
username
:
''
,
name
:
''
},
{
id
:
7
,
username
:
''
,
name
:
''
}]}
|
${
'
2 Assignees
'
}
`
(
'
when assignees have a length of $assignees.length, it renders $expected
'
,
({
assignees
,
expected
})
=>
{
store
.
state
.
issues
[
'
1
'
].
assignees
=
assignees
;
createComponent
();
expect
(
wrapper
.
find
(
BoardEditableItem
).
props
(
'
title
'
)).
toBe
(
expected
);
},
);
describe
(
'
Apollo Schema
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
returns the correct query
'
,
()
=>
{
expect
(
wrapper
.
vm
.
$options
.
apollo
.
participants
.
query
).
toEqual
(
getIssueParticipants
);
});
it
(
'
contains the correct variables
'
,
()
=>
{
const
{
variables
}
=
wrapper
.
vm
.
$options
.
apollo
.
participants
;
const
boundVariable
=
variables
.
bind
(
wrapper
.
vm
);
expect
(
boundVariable
()).
toEqual
({
id
:
'
gid://gitlab/Issue/111
'
});
});
it
(
'
returns the correct data from update
'
,
()
=>
{
const
node
=
{
test
:
1
};
const
{
update
}
=
wrapper
.
vm
.
$options
.
apollo
.
participants
;
expect
(
update
({
issue
:
{
participants
:
{
nodes
:
[
node
]
}
}
})).
toEqual
([
node
]);
});
});
});
spec/frontend/boards/mock_data.js
View file @
7ef0808f
...
...
@@ -319,6 +319,23 @@ export const mockIssuesByListId = {
'
gid://gitlab/List/2
'
:
mockIssues
.
map
(({
id
})
=>
id
),
};
export
const
participants
=
[
{
id
:
'
1
'
,
username
:
'
test
'
,
name
:
'
test
'
,
avatar
:
''
,
avatarUrl
:
''
,
},
{
id
:
'
2
'
,
username
:
'
hello
'
,
name
:
'
hello
'
,
avatar
:
''
,
avatarUrl
:
''
,
},
];
export
const
issues
=
{
[
mockIssue
.
id
]:
mockIssue
,
[
mockIssue2
.
id
]:
mockIssue2
,
...
...
spec/frontend/boards/stores/actions_spec.js
View file @
7ef0808f
...
...
@@ -13,6 +13,7 @@ import actions, { gqlClient } from '~/boards/stores/actions';
import
*
as
types
from
'
~/boards/stores/mutation_types
'
;
import
{
inactiveId
}
from
'
~/boards/constants
'
;
import
issueMoveListMutation
from
'
~/boards/queries/issue_move_list.mutation.graphql
'
;
import
updateAssignees
from
'
~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
'
;
import
{
fullBoardId
,
formatListIssues
,
formatBoardLists
}
from
'
~/boards/boards_util
'
;
const
expectNotImplemented
=
action
=>
{
...
...
@@ -554,6 +555,48 @@ describe('moveIssue', () => {
});
});
describe
(
'
setAssignees
'
,
()
=>
{
const
node
=
{
username
:
'
name
'
};
const
name
=
'
username
'
;
const
projectPath
=
'
h/h
'
;
const
refPath
=
`
${
projectPath
}
#3`
;
const
iid
=
'
1
'
;
beforeEach
(()
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
).
mockResolvedValue
({
data
:
{
issueSetAssignees
:
{
issue
:
{
assignees
:
{
nodes
:
[{
...
node
}]
}
}
}
},
});
});
it
(
'
calls mutate with the correct values
'
,
async
()
=>
{
await
actions
.
setAssignees
(
{
commit
:
()
=>
{},
getters
:
{
getActiveIssue
:
{
iid
,
referencePath
:
refPath
}
}
},
[
name
],
);
expect
(
gqlClient
.
mutate
).
toHaveBeenCalledWith
({
mutation
:
updateAssignees
,
variables
:
{
iid
,
assigneeUsernames
:
[
name
],
projectPath
},
});
});
it
(
'
calls the correct mutation with the correct values
'
,
done
=>
{
testAction
(
actions
.
setAssignees
,
{},
{
getActiveIssue
:
{
iid
,
referencePath
:
refPath
},
commit
:
()
=>
{}
},
[
{
type
:
'
UPDATE_ISSUE_BY_ID
'
,
payload
:
{
prop
:
'
assignees
'
,
issueId
:
undefined
,
value
:
[
node
]
},
},
],
[],
done
,
);
});
});
describe
(
'
createNewIssue
'
,
()
=>
{
expectNotImplemented
(
actions
.
createNewIssue
);
});
...
...
spec/frontend/sidebar/issuable_assignees_spec.js
View file @
7ef0808f
...
...
@@ -13,7 +13,6 @@ describe('IssuableAssignees', () => {
propsData
:
{
...
props
},
});
};
const
findLabel
=
()
=>
wrapper
.
find
(
'
[data-testid="assigneeLabel"
'
);
const
findUncollapsedAssigneeList
=
()
=>
wrapper
.
find
(
UncollapsedAssigneeList
);
const
findEmptyAssignee
=
()
=>
wrapper
.
find
(
'
[data-testid="none"]
'
);
...
...
@@ -30,10 +29,6 @@ describe('IssuableAssignees', () => {
it
(
'
renders "None"
'
,
()
=>
{
expect
(
findEmptyAssignee
().
text
()).
toBe
(
'
None
'
);
});
it
(
'
renders "0 assignees"
'
,
()
=>
{
expect
(
findLabel
().
text
()).
toBe
(
'
0 Assignees
'
);
});
});
describe
(
'
when assignees are present
'
,
()
=>
{
...
...
@@ -42,18 +37,5 @@ describe('IssuableAssignees', () => {
expect
(
findUncollapsedAssigneeList
().
exists
()).
toBe
(
true
);
});
it
.
each
`
assignees | expected
${[{
id
:
1
}]}
|
${
'
Assignee
'
}
${[{
id
:
1
},
{
id
:
2
}]}
|
${
'
2 Assignees
'
}
`
(
'
when assignees have a length of $assignees.length, it renders $expected
'
,
({
assignees
,
expected
})
=>
{
createComponent
({
users
:
assignees
});
expect
(
findLabel
().
text
()).
toBe
(
expected
);
},
);
});
});
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