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
a249542e
Commit
a249542e
authored
Aug 25, 2020
by
Florie Guibert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Swimlanes - Reorder lists
Use drag & drop to reorder lists on board swimlanes
parent
b221119c
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
274 additions
and
47 deletions
+274
-47
app/assets/javascripts/boards/components/board_list_header.vue
...ssets/javascripts/boards/components/board_list_header.vue
+9
-2
app/assets/javascripts/boards/models/list.js
app/assets/javascripts/boards/models/list.js
+1
-1
app/assets/javascripts/boards/queries/board_list_shared.fragment.graphql
...scripts/boards/queries/board_list_shared.fragment.graphql
+1
-0
app/assets/javascripts/boards/queries/board_list_update.mutation.graphql
...scripts/boards/queries/board_list_update.mutation.graphql
+10
-0
app/assets/javascripts/boards/stores/actions.js
app/assets/javascripts/boards/stores/actions.js
+35
-2
app/assets/javascripts/boards/stores/boards_store.js
app/assets/javascripts/boards/stores/boards_store.js
+0
-15
app/assets/javascripts/boards/stores/mutation_types.js
app/assets/javascripts/boards/stores/mutation_types.js
+2
-3
app/assets/javascripts/boards/stores/mutations.js
app/assets/javascripts/boards/stores/mutations.js
+12
-8
app/assets/javascripts/boards/stores/state.js
app/assets/javascripts/boards/stores/state.js
+1
-0
ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
.../assets/javascripts/boards/components/epics_swimlanes.vue
+44
-3
ee/app/assets/javascripts/boards/constants.js
ee/app/assets/javascripts/boards/constants.js
+5
-0
ee/app/assets/javascripts/boards/models/list.js
ee/app/assets/javascripts/boards/models/list.js
+1
-1
ee/app/assets/javascripts/boards/queries/board_list.fragment.graphql
...ts/javascripts/boards/queries/board_list.fragment.graphql
+1
-0
ee/spec/frontend/boards/components/epics_swimlanes_spec.js
ee/spec/frontend/boards/components/epics_swimlanes_spec.js
+66
-3
ee/spec/frontend/boards/mock_data.js
ee/spec/frontend/boards/mock_data.js
+2
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/frontend/boards/stores/actions_spec.js
spec/frontend/boards/stores/actions_spec.js
+52
-1
spec/frontend/boards/stores/mutations_spec.js
spec/frontend/boards/stores/mutations_spec.js
+29
-8
No files found.
app/assets/javascripts/boards/components/board_list_header.vue
View file @
a249542e
<
script
>
import
{
mapActions
}
from
'
vuex
'
;
import
{
GlButton
,
GlButtonGroup
,
...
...
@@ -17,6 +18,7 @@ import boardsStore from '../stores/boards_store';
import
eventHub
from
'
../eventhub
'
;
import
{
ListType
}
from
'
../constants
'
;
import
{
isScopedLabel
}
from
'
~/lib/utils/common_utils
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
export
default
{
components
:
{
...
...
@@ -32,7 +34,7 @@ export default {
directives
:
{
GlTooltip
:
GlTooltipDirective
,
},
mixins
:
[
isWipLimitsOn
],
mixins
:
[
isWipLimitsOn
,
glFeatureFlagMixin
()
],
props
:
{
list
:
{
type
:
Object
,
...
...
@@ -128,6 +130,7 @@ export default {
},
},
methods
:
{
...
mapActions
([
'
updateList
'
]),
showScopedLabels
(
label
)
{
return
boardsStore
.
scopedLabels
.
enabled
&&
isScopedLabel
(
label
);
},
...
...
@@ -144,8 +147,12 @@ export default {
}
if
(
this
.
isLoggedIn
)
{
if
(
this
.
glFeatures
.
boardsWithSwimlanes
&&
this
.
isSwimlanesHeader
)
{
this
.
updateList
({
listId
:
this
.
list
.
id
,
collapsed
:
!
this
.
list
.
isExpanded
});
}
else
{
this
.
list
.
update
();
}
}
// When expanding/collapsing, the tooltip on the caret button sometimes stays open.
// Close all tooltips manually to prevent dangling tooltips.
...
...
app/assets/javascripts/boards/models/list.js
View file @
a249542e
...
...
@@ -47,7 +47,7 @@ class List {
this
.
loading
=
true
;
this
.
loadingMore
=
false
;
this
.
issues
=
obj
.
issues
||
[];
this
.
issuesSize
=
obj
.
issuesSize
?
obj
.
issuesSize
:
0
;
this
.
issuesSize
=
obj
.
issuesSize
||
obj
.
issuesCount
||
0
;
this
.
maxIssueCount
=
obj
.
maxIssueCount
||
obj
.
max_issue_count
||
0
;
if
(
obj
.
label
)
{
...
...
app/assets/javascripts/boards/queries/board_list_shared.fragment.graphql
View file @
a249542e
...
...
@@ -4,6 +4,7 @@ fragment BoardListShared on BoardList {
position
listType
collapsed
issuesCount
label
{
id
title
...
...
app/assets/javascripts/boards/queries/board_list_update.mutation.graphql
0 → 100644
View file @
a249542e
#import "./board_list.fragment.graphql"
mutation
UpdateBoardList
(
$listId
:
ID
!,
$position
:
Int
,
$collapsed
:
Boolean
)
{
updateBoardList
(
input
:
{
listId
:
$listId
,
position
:
$position
,
collapsed
:
$collapsed
})
{
list
{
...
BoardListFragment
}
errors
}
}
app/assets/javascripts/boards/stores/actions.js
View file @
a249542e
...
...
@@ -15,6 +15,7 @@ import projectListsIssuesQuery from '../queries/project_lists_issues.query.graph
import
projectBoardQuery
from
'
../queries/project_board.query.graphql
'
;
import
groupBoardQuery
from
'
../queries/group_board.query.graphql
'
;
import
createBoardListMutation
from
'
../queries/board_list_create.mutation.graphql
'
;
import
updateBoardListMutation
from
'
../queries/board_list_update.mutation.graphql
'
;
const
notImplemented
=
()
=>
{
/* eslint-disable-next-line @gitlab/require-i18n-strings */
...
...
@@ -147,8 +148,40 @@ export default {
notImplemented
();
},
updateList
:
()
=>
{
notImplemented
();
moveList
:
({
state
,
commit
,
dispatch
},
{
listId
,
position
,
moveNewIndexListUp
})
=>
{
const
{
boardLists
}
=
state
;
const
movedList
=
boardLists
.
find
(({
id
})
=>
id
===
listId
);
const
listAtNewIndex
=
boardLists
[
position
+
1
];
movedList
.
position
=
position
;
listAtNewIndex
.
position
=
moveNewIndexListUp
?
listAtNewIndex
.
position
+
1
:
listAtNewIndex
.
position
-
1
;
commit
(
types
.
MOVE_LIST
,
{
movedList
,
listAtNewIndex
,
});
dispatch
(
'
updateList
'
,
{
listId
,
position
});
},
updateList
:
({
commit
},
{
listId
,
position
,
collapsed
})
=>
{
gqlClient
.
mutate
({
mutation
:
updateBoardListMutation
,
variables
:
{
listId
,
position
,
collapsed
,
},
})
.
then
(({
data
})
=>
{
if
(
data
?.
updateBoardList
?.
errors
.
length
)
{
commit
(
types
.
UPDATE_LIST_FAILURE
);
}
})
.
catch
(()
=>
{
commit
(
types
.
UPDATE_LIST_FAILURE
);
});
},
deleteList
:
()
=>
{
...
...
app/assets/javascripts/boards/stores/boards_store.js
View file @
a249542e
...
...
@@ -858,21 +858,6 @@ const boardsStore = {
},
refreshIssueData
(
issue
,
obj
)
{
// issue.id = obj.id;
// issue.iid = obj.iid;
// issue.title = obj.title;
// issue.confidential = obj.confidential;
// issue.dueDate = obj.due_date || obj.dueDate;
// issue.sidebarInfoEndpoint = obj.issue_sidebar_endpoint;
// issue.referencePath = obj.reference_path || obj.referencePath;
// issue.path = obj.real_path || obj.webUrl;
// issue.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint;
// issue.project_id = obj.project_id;
// issue.timeEstimate = obj.time_estimate || obj.timeEstimate;
// issue.assignableLabelsEndpoint = obj.assignable_labels_endpoint;
// issue.blocked = obj.blocked;
// issue.epic = obj.epic;
const
convertedObj
=
convertObjectPropsToCamelCase
(
obj
,
{
dropKeys
:
[
'
issue_sidebar_endpoint
'
,
'
real_path
'
,
'
webUrl
'
],
});
...
...
app/assets/javascripts/boards/stores/mutation_types.js
View file @
a249542e
...
...
@@ -7,9 +7,8 @@ export const SHOW_PROMOTION_LIST = 'SHOW_PROMOTION_LIST';
export
const
REQUEST_ADD_LIST
=
'
REQUEST_ADD_LIST
'
;
export
const
RECEIVE_ADD_LIST_SUCCESS
=
'
RECEIVE_ADD_LIST_SUCCESS
'
;
export
const
RECEIVE_ADD_LIST_ERROR
=
'
RECEIVE_ADD_LIST_ERROR
'
;
export
const
REQUEST_UPDATE_LIST
=
'
REQUEST_UPDATE_LIST
'
;
export
const
RECEIVE_UPDATE_LIST_SUCCESS
=
'
RECEIVE_UPDATE_LIST_SUCCESS
'
;
export
const
RECEIVE_UPDATE_LIST_ERROR
=
'
RECEIVE_UPDATE_LIST_ERROR
'
;
export
const
MOVE_LIST
=
'
MOVE_LIST
'
;
export
const
UPDATE_LIST_FAILURE
=
'
UPDATE_LIST_FAILURE
'
;
export
const
REQUEST_REMOVE_LIST
=
'
REQUEST_REMOVE_LIST
'
;
export
const
RECEIVE_REMOVE_LIST_SUCCESS
=
'
RECEIVE_REMOVE_LIST_SUCCESS
'
;
export
const
RECEIVE_REMOVE_LIST_ERROR
=
'
RECEIVE_REMOVE_LIST_ERROR
'
;
...
...
app/assets/javascripts/boards/stores/mutations.js
View file @
a249542e
import
Vue
from
'
vue
'
;
import
{
sortBy
}
from
'
lodash
'
;
import
*
as
mutationTypes
from
'
./mutation_types
'
;
import
{
__
}
from
'
~/locale
'
;
...
...
@@ -44,16 +46,18 @@ export default {
notImplemented
();
},
[
mutationTypes
.
REQUEST_UPDATE_LIST
]:
()
=>
{
notImplemented
();
[
mutationTypes
.
MOVE_LIST
]:
(
state
,
{
movedList
,
listAtNewIndex
})
=>
{
const
{
boardLists
}
=
state
;
state
.
boardListsPreviousState
=
boardLists
;
const
movedListIndex
=
state
.
boardLists
.
findIndex
(
l
=>
l
.
id
===
movedList
.
id
);
Vue
.
set
(
boardLists
,
movedListIndex
,
movedList
);
Vue
.
set
(
boardLists
,
movedListIndex
.
position
+
1
,
listAtNewIndex
);
state
.
boardLists
=
sortBy
(
boardLists
,
'
position
'
);
},
[
mutationTypes
.
RECEIVE_UPDATE_LIST_SUCCESS
]:
()
=>
{
notImplemented
();
},
[
mutationTypes
.
RECEIVE_UPDATE_LIST_ERROR
]:
()
=>
{
notImplemented
();
[
mutationTypes
.
UPDATE_LIST_FAILURE
]:
state
=>
{
state
.
boardLists
=
state
.
boardListsPreviousState
;
state
.
error
=
__
(
'
An error occurred while updating the list. Please try again.
'
);
},
[
mutationTypes
.
REQUEST_REMOVE_LIST
]:
()
=>
{
...
...
app/assets/javascripts/boards/stores/state.js
View file @
a249542e
...
...
@@ -9,6 +9,7 @@ export default () => ({
activeId
:
inactiveId
,
sidebarType
:
''
,
boardLists
:
[],
boardListsPreviousState
:
[],
issuesByListId
:
{},
issues
:
{},
isLoadingIssues
:
false
,
...
...
ee/app/assets/javascripts/boards/components/epics_swimlanes.vue
View file @
a249542e
<
script
>
import
{
mapActions
,
mapGetters
,
mapState
}
from
'
vuex
'
;
import
{
GlIcon
,
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
Draggable
from
'
vuedraggable
'
;
import
BoardListHeader
from
'
ee_else_ce/boards/components/board_list_header.vue
'
;
import
{
draggableTag
}
from
'
../constants
'
;
import
defaultSortableConfig
from
'
~/sortable/sortable_config
'
;
import
{
n__
}
from
'
~/locale
'
;
import
EpicLane
from
'
./epic_lane.vue
'
;
import
IssuesLaneList
from
'
./issues_lane_list.vue
'
;
...
...
@@ -53,12 +56,44 @@ export default {
unassignedIssuesCountTooltipText
()
{
return
n__
(
`%d unassigned issue`
,
`%d unassigned issues`
,
this
.
unassignedIssuesCount
);
},
treeRootWrapper
()
{
return
this
.
canAdminList
?
Draggable
:
draggableTag
;
},
treeRootOptions
()
{
const
options
=
{
...
defaultSortableConfig
,
fallbackOnBody
:
false
,
group
:
'
board-swimlanes
'
,
tag
:
draggableTag
,
draggable
:
'
.is-draggable
'
,
'
ghost-class
'
:
'
swimlane-header-drag-active
'
,
value
:
this
.
lists
,
};
return
this
.
canAdminList
?
options
:
{};
},
},
mounted
()
{
this
.
fetchIssuesForAllLists
();
},
methods
:
{
...
mapActions
([
'
fetchIssuesForAllLists
'
]),
...
mapActions
([
'
fetchIssuesForAllLists
'
,
'
moveList
'
]),
handleDragOnEnd
(
params
)
{
const
{
newIndex
,
oldIndex
,
item
}
=
params
;
const
{
listId
}
=
item
.
dataset
;
const
newPosition
=
newIndex
-
1
;
let
moveNewIndexListUp
=
false
;
if
(
newIndex
<
oldIndex
)
{
moveNewIndexListUp
=
true
;
}
this
.
moveList
({
listId
,
position
:
newPosition
,
moveNewIndexListUp
,
});
},
},
};
</
script
>
...
...
@@ -68,16 +103,22 @@ export default {
class=
"board-swimlanes gl-white-space-nowrap gl-pb-5 gl-px-3"
data_qa_selector=
"board_epics_swimlanes"
>
<div
<component
:is=
"treeRootWrapper"
v-bind=
"treeRootOptions"
class=
"board-swimlanes-headers gl-display-table gl-sticky gl-pt-5 gl-bg-white gl-top-0 gl-z-index-3"
@
end=
"handleDragOnEnd"
>
<div
v-for=
"list in lists"
:key=
"list.id"
:class=
"
{
'is-collapsed': !list.isExpanded,
'is-draggable': !list.preset,
}"
class="board gl-px-3 gl-vertical-align-top gl-white-space-normal"
:data-list-id="list.id"
data-testid="board-header-container"
>
<board-list-header
:can-admin-list=
"canAdminList"
...
...
@@ -87,7 +128,7 @@ export default {
:is-swimlanes-header=
"true"
/>
</div>
</
div
>
</
component
>
<div
class=
"board-epics-swimlanes gl-display-table"
>
<epic-lane
v-for=
"epic in epics"
...
...
ee/app/assets/javascripts/boards/constants.js
0 → 100644
View file @
a249542e
export
const
draggableTag
=
'
div
'
;
export
default
{
draggableTag
,
};
ee/app/assets/javascripts/boards/models/list.js
View file @
a249542e
...
...
@@ -14,7 +14,7 @@ const EE_TYPES = {
class
ListEE
extends
List
{
constructor
(...
args
)
{
super
(...
args
);
this
.
totalWeight
=
0
;
this
.
totalWeight
=
args
[
0
]?.
totalWeight
||
0
;
}
getTypeInfo
(
type
)
{
...
...
ee/app/assets/javascripts/boards/queries/board_list.fragment.graphql
View file @
a249542e
...
...
@@ -3,6 +3,7 @@
fragment
BoardListFragment
on
BoardList
{
...
BoardListShared
maxIssueCount
totalWeight
assignee
{
id
name
...
...
ee/spec/frontend/boards/components/epics_swimlanes_spec.js
View file @
a249542e
import
Vuex
from
'
vuex
'
;
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
Draggable
from
'
vuedraggable
'
;
import
EpicsSwimlanes
from
'
ee/boards/components/epics_swimlanes.vue
'
;
import
BoardListHeader
from
'
ee_else_ce/boards/components/board_list_header.vue
'
;
import
EpicLane
from
'
ee/boards/components/epic_lane.vue
'
;
import
IssueLaneList
from
'
ee/boards/components/issues_lane_list.vue
'
;
import
getters
from
'
ee/boards/stores/getters
'
;
import
{
draggableTag
}
from
'
ee/boards/constants
'
;
import
{
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
mockListsWithModel
,
mockEpics
,
mockIssuesByListId
,
issues
}
from
'
../mock_data
'
;
...
...
@@ -29,7 +31,7 @@ describe('EpicsSwimlanes', () => {
});
};
const
createComponent
=
()
=>
{
const
createComponent
=
(
props
=
{}
)
=>
{
const
store
=
createStore
();
const
defaultProps
=
{
lists
:
mockListsWithModel
,
...
...
@@ -40,7 +42,7 @@ describe('EpicsSwimlanes', () => {
wrapper
=
shallowMount
(
EpicsSwimlanes
,
{
localVue
,
propsData
:
defaultProps
,
propsData
:
{
...
defaultProps
,
...
props
}
,
store
,
});
};
...
...
@@ -49,6 +51,49 @@ describe('EpicsSwimlanes', () => {
wrapper
.
destroy
();
});
describe
(
'
computed
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
describe
(
'
treeRootWrapper
'
,
()
=>
{
it
(
'
should return Draggable reference when canAdminList prop is true
'
,
()
=>
{
wrapper
.
setProps
({
canAdminList
:
true
});
expect
(
wrapper
.
vm
.
treeRootWrapper
).
toBe
(
Draggable
);
});
it
(
'
should return string "div" when canAdminList prop is false
'
,
()
=>
{
expect
(
wrapper
.
vm
.
treeRootWrapper
).
toBe
(
draggableTag
);
});
});
describe
(
'
treeRootOptions
'
,
()
=>
{
it
(
'
should return object containing Vue.Draggable config extended from `defaultSortableConfig` when canAdminList prop is true
'
,
()
=>
{
wrapper
.
setProps
({
canAdminList
:
true
});
expect
(
wrapper
.
vm
.
treeRootOptions
).
toEqual
(
expect
.
objectContaining
({
animation
:
200
,
forceFallback
:
true
,
fallbackClass
:
'
is-dragging
'
,
fallbackOnBody
:
false
,
ghostClass
:
'
is-ghost
'
,
group
:
'
board-swimlanes
'
,
tag
:
draggableTag
,
draggable
:
'
.is-draggable
'
,
'
ghost-class
'
:
'
swimlane-header-drag-active
'
,
value
:
mockListsWithModel
,
}),
);
});
it
(
'
should return an empty object when canAdminList prop is false
'
,
()
=>
{
expect
(
wrapper
.
vm
.
treeRootOptions
).
toEqual
(
expect
.
objectContaining
({}));
});
});
});
describe
(
'
template
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
...
...
@@ -68,7 +113,25 @@ describe('EpicsSwimlanes', () => {
it
(
'
displays issues icon and count for unassigned issue
'
,
()
=>
{
expect
(
wrapper
.
find
(
GlIcon
).
props
(
'
name
'
)).
toEqual
(
'
issues
'
);
expect
(
wrapper
.
find
(
'
[data-testid="issues-lane-issue-count"
'
).
text
()).
toEqual
(
'
2
'
);
expect
(
wrapper
.
find
(
'
[data-testid="issues-lane-issue-count"]
'
).
text
()).
toEqual
(
'
2
'
);
});
it
(
'
makes non preset lists draggable
'
,
()
=>
{
expect
(
wrapper
.
findAll
(
'
[data-testid="board-header-container"]
'
)
.
at
(
1
)
.
classes
(),
).
toContain
(
'
is-draggable
'
);
});
it
(
'
does not make preset lists draggable
'
,
()
=>
{
expect
(
wrapper
.
findAll
(
'
[data-testid="board-header-container"]
'
)
.
at
(
0
)
.
classes
(),
).
not
.
toContain
(
'
is-draggable
'
);
});
});
});
ee/spec/frontend/boards/mock_data.js
View file @
a249542e
...
...
@@ -12,6 +12,7 @@ export const mockLists = [
maxIssueCount
:
0
,
assignee
:
null
,
milestone
:
null
,
preset
:
true
,
},
{
id
:
'
gid://gitlab/List/2
'
,
...
...
@@ -29,6 +30,7 @@ export const mockLists = [
maxIssueCount
:
0
,
assignee
:
null
,
milestone
:
null
,
preset
:
false
,
},
];
...
...
locale/gitlab.pot
View file @
a249542e
...
...
@@ -2870,6 +2870,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
msgid "An error occurred while updating the list. Please try again."
msgstr ""
msgid "An error occurred while validating group path"
msgstr ""
...
...
spec/frontend/boards/stores/actions_spec.js
View file @
a249542e
import
testAction
from
'
helpers/vuex_action_helper
'
;
import
{
mockListsWithModel
}
from
'
../mock_data
'
;
import
actions
,
{
gqlClient
}
from
'
~/boards/stores/actions
'
;
import
*
as
types
from
'
~/boards/stores/mutation_types
'
;
import
{
inactiveId
,
ListType
}
from
'
~/boards/constants
'
;
...
...
@@ -160,8 +161,58 @@ describe('createList', () => {
});
});
describe
(
'
moveList
'
,
()
=>
{
it
(
'
should commit MOVE_LIST mutation and dispatch updateList action
'
,
done
=>
{
const
state
=
{
endpoints
:
{
fullPath
:
'
gitlab-org
'
,
boardId
:
'
1
'
},
boardType
:
'
group
'
,
disabled
:
false
,
boardLists
:
mockListsWithModel
,
};
testAction
(
actions
.
moveList
,
{
listId
:
'
gid://gitlab/List/1
'
,
position
:
0
,
moveNewIndexListUp
:
true
},
state
,
[
{
type
:
types
.
MOVE_LIST
,
payload
:
{
movedList
:
mockListsWithModel
[
0
],
listAtNewIndex
:
mockListsWithModel
[
1
]
},
},
],
[{
type
:
'
updateList
'
,
payload
:
{
listId
:
'
gid://gitlab/List/1
'
,
position
:
0
}
}],
done
,
);
});
});
describe
(
'
updateList
'
,
()
=>
{
expectNotImplemented
(
actions
.
updateList
);
it
(
'
should commit UPDATE_LIST_FAILURE mutation when API returns an error
'
,
done
=>
{
jest
.
spyOn
(
gqlClient
,
'
mutate
'
).
mockResolvedValue
({
data
:
{
updateBoardList
:
{
list
:
{},
errors
:
[{
foo
:
'
bar
'
}],
},
},
});
const
state
=
{
endpoints
:
{
fullPath
:
'
gitlab-org
'
,
boardId
:
'
1
'
},
boardType
:
'
group
'
,
disabled
:
false
,
boardLists
:
[{
type
:
'
closed
'
}],
};
testAction
(
actions
.
updateList
,
{
listId
:
'
gid://gitlab/List/1
'
,
position
:
1
},
state
,
[{
type
:
types
.
UPDATE_LIST_FAILURE
}],
[],
done
,
);
});
});
describe
(
'
deleteList
'
,
()
=>
{
...
...
spec/frontend/boards/stores/mutations_spec.js
View file @
a249542e
import
mutations
from
'
~/boards/stores/mutations
'
;
import
*
as
types
from
'
~/boards/stores/mutation_types
'
;
import
defaultState
from
'
~/boards/stores/state
'
;
import
{
listObj
,
listObjDuplicate
,
mockIssue
}
from
'
../mock_data
'
;
import
{
listObj
,
listObjDuplicate
,
mockIssue
,
mockListsWithModel
}
from
'
../mock_data
'
;
const
expectNotImplemented
=
action
=>
{
it
(
'
is not implemented
'
,
()
=>
{
...
...
@@ -92,16 +92,37 @@ describe('Board Store Mutations', () => {
expectNotImplemented
(
mutations
.
RECEIVE_ADD_LIST_ERROR
);
});
describe
(
'
REQUEST_UPDATE_LIST
'
,
()
=>
{
expectNotImplemented
(
mutations
.
REQUEST_UPDATE_LIST
);
describe
(
'
MOVE_LIST
'
,
()
=>
{
it
(
'
updates boardLists state with reordered lists and saves previous order
'
,
()
=>
{
state
=
{
...
state
,
boardLists
:
mockListsWithModel
,
};
mutations
.
MOVE_LIST
(
state
,
{
movedList
:
mockListsWithModel
[
0
],
listAtNewIndex
:
mockListsWithModel
[
1
],
});
describe
(
'
RECEIVE_UPDATE_LIST_SUCCESS
'
,
()
=>
{
expectNotImplemented
(
mutations
.
RECEIVE_UPDATE_LIST_SUCCESS
);
expect
(
state
.
boardLists
).
toEqual
([
mockListsWithModel
[
1
],
mockListsWithModel
[
0
]]);
expect
(
state
.
boardListsPreviousState
).
toEqual
(
mockListsWithModel
);
});
});
describe
(
'
RECEIVE_UPDATE_LIST_ERROR
'
,
()
=>
{
expectNotImplemented
(
mutations
.
RECEIVE_UPDATE_LIST_ERROR
);
describe
(
'
UPDATE_LIST_FAILURE
'
,
()
=>
{
it
(
'
updates boardLists state with previous order and sets error message
'
,
()
=>
{
state
=
{
...
state
,
boardLists
:
[
mockListsWithModel
[
1
],
mockListsWithModel
[
0
]],
boardListsPreviousState
:
mockListsWithModel
,
error
:
undefined
,
};
mutations
.
UPDATE_LIST_FAILURE
(
state
);
expect
(
state
.
boardLists
).
toEqual
(
mockListsWithModel
);
expect
(
state
.
error
).
toEqual
(
'
An error occurred while updating the list. Please try again.
'
);
});
});
describe
(
'
REQUEST_REMOVE_LIST
'
,
()
=>
{
...
...
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