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
9828565d
Commit
9828565d
authored
Mar 11, 2021
by
Simon Knox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add assignee to new board list form
Lot of vuex duplication that can be trimmed down later
parent
7a19b738
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
335 additions
and
29 deletions
+335
-29
ee/app/assets/javascripts/boards/components/board_add_new_column.vue
...ts/javascripts/boards/components/board_add_new_column.vue
+65
-4
ee/app/assets/javascripts/boards/graphql/group_board_assignees.query.graphql
...cripts/boards/graphql/group_board_assignees.query.graphql
+16
-0
ee/app/assets/javascripts/boards/graphql/project_board_assignees.query.graphql
...ipts/boards/graphql/project_board_assignees.query.graphql
+16
-0
ee/app/assets/javascripts/boards/stores/actions.js
ee/app/assets/javascripts/boards/stores/actions.js
+48
-0
ee/app/assets/javascripts/boards/stores/mutation_types.js
ee/app/assets/javascripts/boards/stores/mutation_types.js
+3
-0
ee/app/assets/javascripts/boards/stores/mutations.js
ee/app/assets/javascripts/boards/stores/mutations.js
+14
-0
ee/app/assets/javascripts/boards/stores/state.js
ee/app/assets/javascripts/boards/stores/state.js
+2
-0
ee/spec/features/boards/user_adds_lists_to_board_spec.rb
ee/spec/features/boards/user_adds_lists_to_board_spec.rb
+22
-15
ee/spec/frontend/boards/components/board_add_new_column_spec.js
...c/frontend/boards/components/board_add_new_column_spec.js
+44
-3
ee/spec/frontend/boards/mock_data.js
ee/spec/frontend/boards/mock_data.js
+13
-6
ee/spec/frontend/boards/stores/actions_spec.js
ee/spec/frontend/boards/stores/actions_spec.js
+83
-1
locale/gitlab.pot
locale/gitlab.pot
+9
-0
No files found.
ee/app/assets/javascripts/boards/components/board_add_new_column.vue
View file @
9828565d
<
script
>
import
{
GlAvatarLabeled
,
GlFormGroup
,
GlFormRadio
,
GlFormRadioGroup
,
...
...
@@ -19,18 +20,23 @@ export default {
i18n
:
{
listType
:
__
(
'
List type
'
),
labelListDescription
:
__
(
'
A label list displays issues with the selected label.
'
),
assigneeListDescription
:
__
(
'
An assignee list displays issues assigned to the selected user
'
),
milestoneListDescription
:
__
(
'
A milestone list displays issues in the selected milestone.
'
),
selectLabel
:
__
(
'
Select label
'
),
selectAssignee
:
__
(
'
Select assignee
'
),
selectMilestone
:
__
(
'
Select milestone
'
),
searchLabels
:
__
(
'
Search labels
'
),
searchAssignees
:
__
(
'
Search assignees
'
),
searchMilestones
:
__
(
'
Search milestones
'
),
},
columnTypes
:
[
{
value
:
ListType
.
label
,
text
:
__
(
'
Label
'
)
},
{
value
:
ListType
.
assignee
,
text
:
__
(
'
Assignee
'
)
},
{
value
:
ListType
.
milestone
,
text
:
__
(
'
Milestone
'
)
},
],
components
:
{
BoardAddNewColumnForm
,
GlAvatarLabeled
,
GlFormGroup
,
GlFormRadio
,
GlFormRadioGroup
,
...
...
@@ -48,13 +54,23 @@ export default {
};
},
computed
:
{
...
mapState
([
'
labels
'
,
'
labelsLoading
'
,
'
milestones
'
,
'
milestonesLoading
'
]),
...
mapState
([
'
labels
'
,
'
labelsLoading
'
,
'
assignees
'
,
'
assigneesLoading
'
,
'
milestones
'
,
'
milestonesLoading
'
,
]),
...
mapGetters
([
'
getListByTypeId
'
,
'
shouldUseGraphQL
'
,
'
isEpicBoard
'
]),
items
()
{
if
(
this
.
labelTypeSelected
)
{
return
this
.
labels
;
}
if
(
this
.
assigneeTypeSelected
)
{
return
this
.
assignees
;
}
if
(
this
.
milestoneTypeSelected
)
{
return
this
.
milestones
;
}
...
...
@@ -64,6 +80,9 @@ export default {
labelTypeSelected
()
{
return
this
.
columnType
===
ListType
.
label
;
},
assigneeTypeSelected
()
{
return
this
.
columnType
===
ListType
.
assignee
;
},
milestoneTypeSelected
()
{
return
this
.
columnType
===
ListType
.
milestone
;
},
...
...
@@ -74,6 +93,12 @@ export default {
}
return
this
.
labels
.
find
(({
id
})
=>
id
===
this
.
selectedId
);
},
selectedAssignee
()
{
if
(
!
this
.
assigneeTypeSelected
)
{
return
null
;
}
return
this
.
assignees
.
find
(({
id
})
=>
id
===
this
.
selectedId
);
},
selectedMilestone
()
{
if
(
!
this
.
milestoneTypeSelected
)
{
return
null
;
...
...
@@ -87,6 +112,9 @@ export default {
if
(
this
.
labelTypeSelected
)
{
return
this
.
selectedLabel
;
}
if
(
this
.
assigneeTypeSelected
)
{
return
this
.
selectedAssignee
;
}
if
(
this
.
milestoneTypeSelected
)
{
return
this
.
selectedMilestone
;
}
...
...
@@ -108,6 +136,9 @@ export default {
if
(
this
.
columnType
===
ListType
.
label
)
{
return
this
.
labelsLoading
;
}
if
(
this
.
assigneeTypeSelected
)
{
return
this
.
assigneesLoading
;
}
if
(
this
.
columnType
===
ListType
.
milestone
)
{
return
this
.
milestonesLoading
;
}
...
...
@@ -119,6 +150,10 @@ export default {
return
this
.
$options
.
i18n
.
labelListDescription
;
}
if
(
this
.
assigneeTypeSelected
)
{
return
this
.
$options
.
i18n
.
assigneeListDescription
;
}
if
(
this
.
milestoneTypeSelected
)
{
return
this
.
$options
.
i18n
.
milestoneListDescription
;
}
...
...
@@ -131,6 +166,10 @@ export default {
return
this
.
$options
.
i18n
.
selectLabel
;
}
if
(
this
.
assigneeTypeSelected
)
{
return
this
.
$options
.
i18n
.
selectAssignee
;
}
if
(
this
.
milestoneTypeSelected
)
{
return
this
.
$options
.
i18n
.
selectMilestone
;
}
...
...
@@ -143,6 +182,10 @@ export default {
return
this
.
$options
.
i18n
.
searchLabels
;
}
if
(
this
.
assigneeTypeSelected
)
{
return
this
.
$options
.
i18n
.
searchAssignees
;
}
if
(
this
.
milestoneTypeSelected
)
{
return
this
.
$options
.
i18n
.
searchMilestones
;
}
...
...
@@ -159,6 +202,7 @@ export default {
'
fetchLabels
'
,
'
highlightList
'
,
'
setAddColumnFormVisibility
'
,
'
fetchAssignees
'
,
'
fetchMilestones
'
,
]),
highlight
(
listId
)
{
...
...
@@ -206,6 +250,11 @@ export default {
...
this
.
selectedMilestone
,
id
:
getIdFromGraphQLId
(
this
.
selectedMilestone
.
id
),
};
}
else
if
(
this
.
assigneeTypeSelected
)
{
listObj
.
assignee
=
{
...
this
.
selectedAssignee
,
id
:
getIdFromGraphQLId
(
this
.
selectedAssignee
.
id
),
};
}
boardsStore
.
new
(
listObj
);
...
...
@@ -217,6 +266,9 @@ export default {
case
ListType
.
milestone
:
this
.
fetchMilestones
(
searchTerm
);
break
;
case
ListType
.
assignee
:
this
.
fetchAssignees
(
searchTerm
);
break
;
case
ListType
.
label
:
default
:
this
.
fetchLabels
(
searchTerm
);
...
...
@@ -227,7 +279,8 @@ export default {
return
this
.
scopedLabelsAvailable
&&
isScopedLabel
(
label
);
},
setColumnType
()
{
setColumnType
(
type
)
{
this
.
columnType
=
type
;
this
.
selectedId
=
null
;
this
.
filterItems
();
},
...
...
@@ -287,7 +340,7 @@ export default {
:key=
"item.id"
class=
"gl-display-flex gl-flex-align-items-center gl-mb-5 gl-font-weight-normal"
>
<gl-form-radio
:value=
"item.id"
class=
"gl-mb-0"
/>
<gl-form-radio
:value=
"item.id"
class=
"gl-mb-0
gl-align-self-center
"
/>
<span
v-if=
"labelTypeSelected"
class=
"dropdown-label-box gl-top-0"
...
...
@@ -295,7 +348,15 @@ export default {
backgroundColor: item.color,
}"
>
</span>
<span>
{{
item
.
title
}}
</span>
<gl-avatar-labeled
v-if=
"assigneeTypeSelected"
:size=
"32"
:label=
"item.name"
:sub-label=
"item.username"
:src=
"item.avatarUrl"
/>
<span
v-else
>
{{
item
.
title
}}
</span>
</label>
</gl-form-radio-group>
</
template
>
...
...
ee/app/assets/javascripts/boards/graphql/group_board_assignees.query.graphql
0 → 100644
View file @
9828565d
#import "~/graphql_shared/fragments/user.fragment.graphql"
query
GroupBoardAssignees
(
$fullPath
:
ID
!,
$search
:
String
)
{
workspace
:
group
(
fullPath
:
$fullPath
)
{
__typename
assignees
:
groupMembers
(
search
:
$search
)
{
__typename
nodes
{
id
user
{
...
User
}
}
}
}
}
ee/app/assets/javascripts/boards/graphql/project_board_assignees.query.graphql
0 → 100644
View file @
9828565d
#import "~/graphql_shared/fragments/user.fragment.graphql"
query
ProjectBoardAssignees
(
$fullPath
:
ID
!,
$search
:
String
)
{
workspace
:
project
(
fullPath
:
$fullPath
)
{
__typename
assignees
:
projectMembers
(
search
:
$search
)
{
__typename
nodes
{
id
user
{
...
User
}
}
}
}
}
ee/app/assets/javascripts/boards/stores/actions.js
View file @
9828565d
...
...
@@ -34,12 +34,14 @@ import createEpicBoardListMutation from '../graphql/epic_board_list_create.mutat
import
epicBoardListsQuery
from
'
../graphql/epic_board_lists.query.graphql
'
;
import
epicMoveListMutation
from
'
../graphql/epic_move_list.mutation.graphql
'
;
import
epicsSwimlanesQuery
from
'
../graphql/epics_swimlanes.query.graphql
'
;
import
groupBoardAssigneesQuery
from
'
../graphql/group_board_assignees.query.graphql
'
;
import
groupBoardMilestonesQuery
from
'
../graphql/group_board_milestones.query.graphql
'
;
import
issueMoveListMutation
from
'
../graphql/issue_move_list.mutation.graphql
'
;
import
issueSetEpicMutation
from
'
../graphql/issue_set_epic.mutation.graphql
'
;
import
issueSetWeightMutation
from
'
../graphql/issue_set_weight.mutation.graphql
'
;
import
listUpdateLimitMetricsMutation
from
'
../graphql/list_update_limit_metrics.mutation.graphql
'
;
import
listsEpicsQuery
from
'
../graphql/lists_epics.query.graphql
'
;
import
projectBoardAssigneesQuery
from
'
../graphql/project_board_assignees.query.graphql
'
;
import
projectBoardMilestonesQuery
from
'
../graphql/project_board_milestones.query.graphql
'
;
import
updateBoardEpicUserPreferencesMutation
from
'
../graphql/update_board_epic_user_preferences.mutation.graphql
'
;
...
...
@@ -646,6 +648,52 @@ export default {
});
},
fetchAssignees
({
state
,
commit
},
search
)
{
commit
(
types
.
RECEIVE_ASSIGNEES_REQUEST
);
const
{
fullPath
,
boardType
}
=
state
;
const
variables
=
{
fullPath
,
search
,
};
let
query
;
if
(
boardType
===
BoardType
.
project
)
{
query
=
projectBoardAssigneesQuery
;
}
if
(
boardType
===
BoardType
.
group
)
{
query
=
groupBoardAssigneesQuery
;
}
if
(
!
query
)
{
// eslint-disable-next-line @gitlab/require-i18n-strings
throw
new
Error
(
'
Unknown board type
'
);
}
return
gqlClient
.
query
({
query
,
variables
,
})
.
then
(({
data
})
=>
{
const
[
firstError
]
=
data
.
workspace
.
errors
||
[];
const
assignees
=
data
.
workspace
.
assignees
.
nodes
;
if
(
firstError
)
{
throw
new
Error
(
firstError
);
}
commit
(
types
.
RECEIVE_ASSIGNEES_SUCCESS
,
assignees
.
map
(({
user
})
=>
user
),
);
})
.
catch
((
e
)
=>
{
commit
(
types
.
RECEIVE_ASSIGNEES_FAILURE
);
throw
e
;
});
},
createList
:
({
getters
,
dispatch
},
{
backlog
,
labelId
,
milestoneId
,
assigneeId
})
=>
{
if
(
!
getters
.
isEpicBoard
)
{
dispatch
(
'
createIssueList
'
,
{
backlog
,
labelId
,
milestoneId
,
assigneeId
});
...
...
ee/app/assets/javascripts/boards/stores/mutation_types.js
View file @
9828565d
...
...
@@ -38,3 +38,6 @@ export const SET_BOARD_EPIC_USER_PREFERENCES = 'SET_BOARD_EPIC_USER_PREFERENCES'
export
const
RECEIVE_MILESTONES_REQUEST
=
'
RECEIVE_MILESTONES_REQUEST
'
;
export
const
RECEIVE_MILESTONES_SUCCESS
=
'
RECEIVE_MILESTONES_SUCCESS
'
;
export
const
RECEIVE_MILESTONES_FAILURE
=
'
RECEIVE_MILESTONES_FAILURE
'
;
export
const
RECEIVE_ASSIGNEES_REQUEST
=
'
RECEIVE_ASSIGNEES_REQUEST
'
;
export
const
RECEIVE_ASSIGNEES_SUCCESS
=
'
RECEIVE_ASSIGNEES_SUCCESS
'
;
export
const
RECEIVE_ASSIGNEES_FAILURE
=
'
RECEIVE_ASSIGNEES_FAILURE
'
;
ee/app/assets/javascripts/boards/stores/mutations.js
View file @
9828565d
...
...
@@ -232,4 +232,18 @@ export default {
state
.
milestonesLoading
=
false
;
state
.
error
=
__
(
'
Failed to load milestones.
'
);
},
[
mutationTypes
.
RECEIVE_ASSIGNEES_REQUEST
](
state
)
{
state
.
assigneesLoading
=
true
;
},
[
mutationTypes
.
RECEIVE_ASSIGNEES_SUCCESS
](
state
,
assignees
)
{
state
.
assignees
=
assignees
;
state
.
assigneesLoading
=
false
;
},
[
mutationTypes
.
RECEIVE_ASSIGNEES_FAILURE
](
state
)
{
state
.
assigneesLoading
=
false
;
state
.
error
=
__
(
'
Failed to load assignees.
'
);
},
};
ee/app/assets/javascripts/boards/stores/state.js
View file @
9828565d
...
...
@@ -14,4 +14,6 @@ export default () => ({
epicsFlags
:
{},
milestones
:
[],
milestonesLoading
:
false
,
assignees
:
[],
assigneesLoading
:
false
,
});
ee/spec/features/boards/user_adds_lists_to_board_spec.rb
View file @
9828565d
...
...
@@ -15,7 +15,8 @@ RSpec.describe 'User adds milestone lists', :js do
let_it_be
(
:group_backlog_list
)
{
create
(
:backlog_list
,
board:
group_board
)
}
let_it_be
(
:issue
)
{
create
(
:issue
,
project:
project
,
milestone:
milestone
)
}
let_it_be
(
:issue_with_milestone
)
{
create
(
:issue
,
project:
project
,
milestone:
milestone
)
}
let_it_be
(
:issue_with_assignee
)
{
create
(
:issue
,
project:
project
,
assignees:
[
user
])
}
before_all
do
project
.
add_maintainer
(
user
)
...
...
@@ -31,7 +32,10 @@ RSpec.describe 'User adds milestone lists', :js do
with_them
do
before
do
stub_licensed_features
(
board_milestone_lists:
true
)
stub_licensed_features
(
board_milestone_lists:
true
,
board_assignee_lists:
true
)
sign_in
(
user
)
set_cookie
(
'sidebar_collapsed'
,
'true'
)
...
...
@@ -51,28 +55,31 @@ RSpec.describe 'User adds milestone lists', :js do
end
it
'creates milestone column'
do
click_button
button_text
wait_for_all_requests
select
(
'Milestone'
,
from:
'List type'
)
add_list
(
'Milestone'
,
milestone
.
title
)
add_milestone_list
(
milestone
)
expect
(
page
).
to
have_selector
(
'.board'
,
text:
milestone
.
title
)
expect
(
find
(
'.board:nth-child(2) .board-card'
)).
to
have_content
(
issue_with_milestone
.
title
)
end
wait_for_all_requests
it
'creates assignee column'
do
add_list
(
'Assignee'
,
user
.
name
)
expect
(
page
).
to
have_selector
(
'.board'
,
text:
milestone
.
titl
e
)
expect
(
find
(
'.board:nth-child(2) .board-card'
)).
to
have_content
(
issue
.
title
)
expect
(
page
).
to
have_selector
(
'.board'
,
text:
user
.
nam
e
)
expect
(
find
(
'.board:nth-child(2) .board-card'
)).
to
have_content
(
issue
_with_assignee
.
title
)
end
end
def
add_milestone_list
(
milestone
)
def
add_list
(
list_type
,
title
)
click_button
'Create list'
wait_for_all_requests
select
(
list_type
,
from:
'List type'
)
page
.
within
(
'.board-add-new-list'
)
do
find
(
'label'
,
text:
milestone
.
title
).
click
find
(
'label'
,
text:
title
).
click
click_button
'Add'
end
end
def
button_text
'Create list'
wait_for_all_requests
end
end
ee/spec/frontend/boards/components/board_add_new_column_spec.js
View file @
9828565d
import
{
Gl
SearchBoxByType
}
from
'
@gitlab/ui
'
;
import
{
Gl
AvatarLabeled
,
GlSearchBoxByType
,
GlFormSelect
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
Vue
,
{
nextTick
}
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
BoardAddNewColumn
from
'
ee/boards/components/board_add_new_column.vue
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
import
BoardAddNewColumnForm
from
'
~/boards/components/board_add_new_column_form.vue
'
;
import
{
ListType
}
from
'
~/boards/constants
'
;
import
defaultState
from
'
~/boards/stores/state
'
;
import
{
mockLists
}
from
'
../mock_data
'
;
import
{
mock
Assignees
,
mock
Lists
}
from
'
../mock_data
'
;
const
mockLabelList
=
mockLists
[
1
];
Vue
.
use
(
Vuex
);
describe
(
'
Board
card layout
'
,
()
=>
{
describe
(
'
Board
AddNewColumn
'
,
()
=>
{
let
wrapper
;
let
shouldUseGraphQL
;
...
...
@@ -30,6 +31,7 @@ describe('Board card layout', () => {
const
mountComponent
=
({
selectedId
,
labels
=
[],
assignees
=
[],
getListByTypeId
=
jest
.
fn
(),
actions
=
{},
}
=
{})
=>
{
...
...
@@ -57,6 +59,8 @@ describe('Board card layout', () => {
state
:
{
labels
,
labelsLoading
:
false
,
assignees
,
assigneesLoading
:
false
,
},
}),
provide
:
{
...
...
@@ -71,10 +75,12 @@ describe('Board card layout', () => {
wrapper
=
null
;
});
const
findForm
=
()
=>
wrapper
.
findComponent
(
BoardAddNewColumnForm
);
const
formTitle
=
()
=>
wrapper
.
findByTestId
(
'
board-add-column-form-title
'
).
text
();
const
findSearchInput
=
()
=>
wrapper
.
find
(
GlSearchBoxByType
);
const
cancelButton
=
()
=>
wrapper
.
findByTestId
(
'
cancelAddNewColumn
'
);
const
submitButton
=
()
=>
wrapper
.
findByTestId
(
'
addNewColumnButton
'
);
const
listTypeSelect
=
()
=>
wrapper
.
findComponent
(
GlFormSelect
);
beforeEach
(()
=>
{
shouldUseGraphQL
=
true
;
...
...
@@ -152,4 +158,39 @@ describe('Board card layout', () => {
expect
(
createList
).
not
.
toHaveBeenCalled
();
});
});
describe
(
'
assignee list
'
,
()
=>
{
beforeEach
(
async
()
=>
{
mountComponent
({
assignees
:
mockAssignees
,
actions
:
{
fetchAssignees
:
jest
.
fn
(),
},
});
listTypeSelect
().
vm
.
$emit
(
'
change
'
,
ListType
.
assignee
);
await
nextTick
();
});
it
(
'
sets assignee placeholder text in form
'
,
async
()
=>
{
expect
(
findForm
().
props
()).
toMatchObject
({
formDescription
:
BoardAddNewColumn
.
i18n
.
assigneeListDescription
,
searchLabel
:
BoardAddNewColumn
.
i18n
.
selectAssignee
,
searchPlaceholder
:
BoardAddNewColumn
.
i18n
.
searchAssignees
,
});
});
it
(
'
shows list of assignees
'
,
()
=>
{
const
userList
=
wrapper
.
findAllComponents
(
GlAvatarLabeled
);
const
[
firstUser
]
=
mockAssignees
;
expect
(
userList
).
toHaveLength
(
mockAssignees
.
length
);
expect
(
userList
.
at
(
0
).
props
()).
toMatchObject
({
label
:
firstUser
.
name
,
subLabel
:
firstUser
.
username
,
});
});
});
});
ee/spec/frontend/boards/mock_data.js
View file @
9828565d
...
...
@@ -76,7 +76,7 @@ const defaultDescendantCounts = {
closedIssues
:
0
,
};
const
a
ssignees
=
[
export
const
mockA
ssignees
=
[
{
id
:
'
gid://gitlab/User/2
'
,
username
:
'
angelina.herman
'
,
...
...
@@ -84,6 +84,13 @@ const assignees = [
avatar
:
'
https://www.gravatar.com/avatar/eb7b664b13a30ad9f9ba4b61d7075470?s=80&d=identicon
'
,
webUrl
:
'
http://127.0.0.1:3000/angelina.herman
'
,
},
{
id
:
'
gid://gitlab/User/118
'
,
username
:
'
jacklyn.moore
'
,
name
:
'
Brock Jaskolski
'
,
avatar
:
'
https://www.gravatar.com/avatar/af29c072d9fcf315772cfd802c7a7d35?s=80&d=identicon
'
,
webUrl
:
'
http://127.0.0.1:3000/jacklyn.moore
'
,
},
];
export
const
mockMilestones
=
[
...
...
@@ -127,7 +134,7 @@ export const rawIssue = {
],
},
assignees
:
{
nodes
:
a
ssignees
,
nodes
:
mockA
ssignees
,
},
epic
:
{
id
:
'
gid://gitlab/Epic/41
'
,
...
...
@@ -147,7 +154,7 @@ export const mockIssue = {
weight
:
null
,
confidential
:
false
,
path
:
`/
${
mockIssueProjectPath
}
/-/issues/27`
,
assignees
,
assignees
:
mockAssignees
,
labels
,
epic
:
{
id
:
'
gid://gitlab/Epic/41
'
,
...
...
@@ -165,7 +172,7 @@ export const mockIssue2 = {
weight
:
null
,
confidential
:
false
,
path
:
'
/gitlab-org/gitlab-test/-/issues/28
'
,
assignees
,
assignees
:
mockAssignees
,
labels
,
epic
:
{
id
:
'
gid://gitlab/Epic/40
'
,
...
...
@@ -183,7 +190,7 @@ export const mockIssue3 = {
weight
:
null
,
confidential
:
false
,
path
:
'
/gitlab-org/gitlab-test/-/issues/28
'
,
assignees
,
assignees
:
mockAssignees
,
labels
,
epic
:
null
,
};
...
...
@@ -198,7 +205,7 @@ export const mockIssue4 = {
weight
:
null
,
confidential
:
false
,
path
:
'
/gitlab-org/gitlab-test/-/issues/28
'
,
assignees
,
assignees
:
mockAssignees
,
labels
,
epic
:
null
,
};
...
...
ee/spec/frontend/boards/stores/actions_spec.js
View file @
9828565d
...
...
@@ -19,9 +19,10 @@ import {
mockIssue
,
mockIssue2
,
mockEpic
,
mockEpics
,
rawIssue
,
mockMilestones
,
mockAssignees
,
mockEpics
,
}
from
'
../mock_data
'
;
Vue
.
use
(
Vuex
);
...
...
@@ -1268,3 +1269,84 @@ describe('fetchMilestones', () => {
});
});
});
describe
(
'
fetchAssignees
'
,
()
=>
{
const
queryResponse
=
{
data
:
{
workspace
:
{
assignees
:
{
nodes
:
mockAssignees
.
map
((
assignee
)
=>
({
user
:
assignee
})),
},
},
},
};
const
queryErrors
=
{
data
:
{
project
:
{
errors
:
[
'
You cannot view these assignees
'
],
assignees
:
{},
},
},
};
function
createStore
({
state
=
{
boardType
:
'
project
'
,
fullPath
:
'
gitlab-org/gitlab
'
,
assignees
:
[],
assigneesLoading
:
false
,
},
}
=
{})
{
return
new
Vuex
.
Store
({
state
,
mutations
,
});
}
it
(
'
throws error if state.boardType is not group or project
'
,
()
=>
{
const
store
=
createStore
({
state
:
{
boardType
:
'
invalid
'
,
},
});
expect
(()
=>
actions
.
fetchAssignees
(
store
)).
toThrow
(
new
Error
(
'
Unknown board type
'
));
});
it
(
'
sets assigneesLoading to true
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
query
'
).
mockResolvedValue
(
queryResponse
);
const
store
=
createStore
();
actions
.
fetchAssignees
(
store
);
expect
(
store
.
state
.
assigneesLoading
).
toBe
(
true
);
});
describe
(
'
success
'
,
()
=>
{
it
(
'
sets state.assignees from query result
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
query
'
).
mockResolvedValue
(
queryResponse
);
const
store
=
createStore
();
await
actions
.
fetchAssignees
(
store
);
expect
(
store
.
state
.
assigneesLoading
).
toBe
(
false
);
expect
(
store
.
state
.
assignees
).
toEqual
(
expect
.
objectContaining
(
mockAssignees
));
});
});
describe
(
'
failure
'
,
()
=>
{
it
(
'
throws an error and displays an error message
'
,
async
()
=>
{
jest
.
spyOn
(
gqlClient
,
'
query
'
).
mockResolvedValue
(
queryErrors
);
const
store
=
createStore
();
await
expect
(
actions
.
fetchAssignees
(
store
)).
rejects
.
toThrow
();
expect
(
store
.
state
.
assigneesLoading
).
toBe
(
false
);
expect
(
store
.
state
.
error
).
toBe
(
'
Failed to load assignees.
'
);
});
});
});
locale/gitlab.pot
View file @
9828565d
...
...
@@ -3224,6 +3224,9 @@ msgstr ""
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
msgid "An assignee list displays issues assigned to the selected user"
msgstr ""
msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
msgstr ""
...
...
@@ -12629,6 +12632,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
msgid "Failed to load assignees."
msgstr ""
msgid "Failed to load assignees. Please try again."
msgstr ""
...
...
@@ -26413,6 +26419,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
msgid "Search assignees"
msgstr ""
msgid "Search authors"
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