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
6fbd2c64
Commit
6fbd2c64
authored
Nov 03, 2020
by
Kushal Pandya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for bulk editing sidebar
Adds support for bulk editing Issuables via sidebar.
parent
b16a1537
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
437 additions
and
8 deletions
+437
-8
app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue
...s/issuable_list/components/issuable_bulk_edit_sidebar.vue
+35
-0
app/assets/javascripts/issuable_list/components/issuable_item.vue
...ts/javascripts/issuable_list/components/issuable_item.vue
+19
-2
app/assets/javascripts/issuable_list/components/issuable_list_root.vue
...vascripts/issuable_list/components/issuable_list_root.vue
+76
-1
app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
...mponents/filtered_search_bar/filtered_search_bar_root.vue
+18
-0
spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js
...suable_list/components/issuable_bulk_edit_sidebar_spec.js
+97
-0
spec/frontend/issuable_list/components/issuable_item_spec.js
spec/frontend/issuable_list/components/issuable_item_spec.js
+21
-1
spec/frontend/issuable_list/components/issuable_list_root_spec.js
...ntend/issuable_list/components/issuable_list_root_spec.js
+139
-3
spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
...ents/filtered_search_bar/filtered_search_bar_root_spec.js
+32
-1
No files found.
app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue
0 → 100644
View file @
6fbd2c64
<
script
>
export
default
{
props
:
{
expanded
:
{
type
:
Boolean
,
required
:
true
,
},
},
watch
:
{
expanded
(
value
)
{
const
layoutPageEl
=
document
.
querySelector
(
'
.layout-page
'
);
if
(
layoutPageEl
)
{
layoutPageEl
.
classList
.
toggle
(
'
right-sidebar-expanded
'
,
value
);
layoutPageEl
.
classList
.
toggle
(
'
right-sidebar-collapsed
'
,
!
value
);
}
},
},
};
</
script
>
<
template
>
<aside
:class=
"
{ 'right-sidebar-expanded': expanded, 'right-sidebar-collapsed': !expanded }"
class="issues-bulk-update right-sidebar"
aria-live="polite"
>
<div
class=
"gl-display-flex gl-justify-content-space-between gl-p-4 gl-border-b-1 gl-border-b-solid gl-border-gray-100"
>
<slot
name=
"bulk-edit-actions"
></slot>
</div>
<slot
name=
"sidebar-items"
></slot>
</aside>
</
template
>
app/assets/javascripts/issuable_list/components/issuable_item.vue
View file @
6fbd2c64
<
script
>
import
{
GlLink
,
GlIcon
,
GlLabel
,
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
{
GlLink
,
GlIcon
,
GlLabel
,
Gl
FormCheckbox
,
Gl
TooltipDirective
}
from
'
@gitlab/ui
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
...
...
@@ -14,6 +14,7 @@ export default {
GlLink
,
GlIcon
,
GlLabel
,
GlFormCheckbox
,
IssuableAssignees
,
},
directives
:
{
...
...
@@ -33,6 +34,15 @@ export default {
type
:
Boolean
,
required
:
true
,
},
showCheckbox
:
{
type
:
Boolean
,
required
:
true
,
},
checked
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
author
()
{
...
...
@@ -109,8 +119,15 @@ export default {
</
script
>
<
template
>
<li
class=
"issue
px-3
"
>
<li
class=
"issue
gl-px-5!
"
>
<div
class=
"issue-box"
>
<div
v-if=
"showCheckbox"
class=
"issue-check"
>
<gl-form-checkbox
class=
"gl-mr-0"
:checked=
"checked"
@
input=
"$emit('checked-input', $event)"
/>
</div>
<div
class=
"issuable-info-container"
>
<div
class=
"issuable-main-info"
>
<div
data-testid=
"issuable-title"
class=
"issue-title title"
>
...
...
app/assets/javascripts/issuable_list/components/issuable_list_root.vue
View file @
6fbd2c64
<
script
>
import
{
GlSkeletonLoading
,
GlPagination
}
from
'
@gitlab/ui
'
;
import
{
uniqueId
}
from
'
lodash
'
;
import
{
updateHistory
,
setUrlParams
}
from
'
~/lib/utils/url_utility
'
;
import
FilteredSearchBar
from
'
~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
'
;
import
IssuableTabs
from
'
./issuable_tabs.vue
'
;
import
IssuableItem
from
'
./issuable_item.vue
'
;
import
IssuableBulkEditSidebar
from
'
./issuable_bulk_edit_sidebar.vue
'
;
import
{
DEFAULT_SKELETON_COUNT
}
from
'
../constants
'
;
...
...
@@ -15,6 +17,7 @@ export default {
IssuableTabs
,
FilteredSearchBar
,
IssuableItem
,
IssuableBulkEditSidebar
,
GlPagination
,
},
props
:
{
...
...
@@ -85,6 +88,11 @@ export default {
required
:
false
,
default
:
false
,
},
showBulkEditSidebar
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
defaultPageSize
:
{
type
:
Number
,
required
:
false
,
...
...
@@ -116,6 +124,11 @@ export default {
default
:
true
,
},
},
data
()
{
return
{
checkedIssuables
:
{},
};
},
computed
:
{
skeletonItemCount
()
{
const
{
totalItems
,
defaultPageSize
,
currentPage
}
=
this
;
...
...
@@ -128,8 +141,40 @@ export default {
}
return
DEFAULT_SKELETON_COUNT
;
},
allIssuablesChecked
()
{
return
this
.
bulkEditIssuables
.
length
===
this
.
issuables
.
length
;
},
/**
* Returns all the checked issuables from `checkedIssuables` map.
*/
bulkEditIssuables
()
{
return
Object
.
keys
(
this
.
checkedIssuables
).
reduce
((
acc
,
issuableId
)
=>
{
if
(
this
.
checkedIssuables
[
issuableId
].
checked
)
{
acc
.
push
(
this
.
checkedIssuables
[
issuableId
].
issuable
);
}
return
acc
;
},
[]);
},
},
watch
:
{
issuables
(
list
)
{
this
.
checkedIssuables
=
list
.
reduce
((
acc
,
issuable
)
=>
{
const
id
=
this
.
issuableId
(
issuable
);
acc
[
id
]
=
{
// By default, an issuable is not checked,
// But if `checkedIssuables` is already
// populated, use existing value.
checked
:
typeof
this
.
checkedIssuables
[
id
]
!==
'
boolean
'
?
false
:
this
.
checkedIssuables
[
id
].
checked
,
// We're caching issuable reference here
// for ease of populating in `bulkEditIssuables`.
issuable
,
};
return
acc
;
},
{});
},
urlParams
:
{
deep
:
true
,
immediate
:
true
,
...
...
@@ -144,6 +189,22 @@ export default {
},
},
},
methods
:
{
issuableId
(
issuable
)
{
return
issuable
.
id
||
issuable
.
iid
||
uniqueId
();
},
issuableChecked
(
issuable
)
{
return
this
.
checkedIssuables
[
this
.
issuableId
(
issuable
)]?.
checked
;
},
handleIssuableCheckedInput
(
issuable
,
value
)
{
this
.
checkedIssuables
[
this
.
issuableId
(
issuable
)].
checked
=
value
;
},
handleAllIssuablesCheckedInput
(
value
)
{
Object
.
keys
(
this
.
checkedIssuables
).
forEach
(
issuableId
=>
{
this
.
checkedIssuables
[
issuableId
].
checked
=
value
;
});
},
},
};
</
script
>
...
...
@@ -167,10 +228,21 @@ export default {
:sort-options=
"sortOptions"
:initial-filter-value=
"initialFilterValue"
:initial-sort-by=
"initialSortBy"
:show-checkbox=
"showBulkEditSidebar"
:checkbox-checked=
"allIssuablesChecked"
class=
"gl-flex-grow-1 row-content-block"
@
checked-input=
"handleAllIssuablesCheckedInput"
@
onFilter=
"$emit('filter', $event)"
@
onSort=
"$emit('sort', $event)"
/>
<issuable-bulk-edit-sidebar
:expanded=
"showBulkEditSidebar"
>
<
template
#bulk-edit-actions
>
<slot
name=
"bulk-edit-actions"
:checked-issuables=
"bulkEditIssuables"
></slot>
</
template
>
<
template
#sidebar-items
>
<slot
name=
"sidebar-items"
:checked-issuables=
"bulkEditIssuables"
></slot>
</
template
>
</issuable-bulk-edit-sidebar>
<div
class=
"issuables-holder"
>
<ul
v-if=
"issuablesLoading"
class=
"content-list"
>
<li
v-for=
"n in skeletonItemCount"
:key=
"n"
class=
"issue gl-px-5! gl-py-5!"
>
...
...
@@ -183,10 +255,13 @@ export default {
>
<issuable-item
v-for=
"issuable in issuables"
:key=
"issuable
.id
"
:key=
"issuable
Id(issuable)
"
:issuable-symbol=
"issuableSymbol"
:issuable=
"issuable"
:enable-label-permalinks=
"enableLabelPermalinks"
:show-checkbox=
"showBulkEditSidebar"
:checked=
"issuableChecked(issuable)"
@
checked-input=
"handleIssuableCheckedInput(issuable, $event)"
>
<
template
#reference
>
<slot
name=
"reference"
:issuable=
"issuable"
></slot>
...
...
app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
View file @
6fbd2c64
...
...
@@ -5,6 +5,7 @@ import {
GlButton
,
GlDropdown
,
GlDropdownItem
,
GlFormCheckbox
,
GlTooltipDirective
,
}
from
'
@gitlab/ui
'
;
...
...
@@ -25,6 +26,7 @@ export default {
GlButton
,
GlDropdown
,
GlDropdownItem
,
GlFormCheckbox
,
},
directives
:
{
GlTooltip
:
GlTooltipDirective
,
...
...
@@ -59,6 +61,16 @@ export default {
default
:
''
,
validator
:
value
=>
value
===
''
||
/
(
_desc
)
|
(
_asc
)
/g
.
test
(
value
),
},
showCheckbox
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
checkboxChecked
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
searchInputPlaceholder
:
{
type
:
String
,
required
:
true
,
...
...
@@ -291,6 +303,12 @@ export default {
<
template
>
<div
class=
"vue-filtered-search-bar-container d-md-flex"
>
<gl-form-checkbox
v-if=
"showCheckbox"
class=
"gl-align-self-center"
:checked=
"checkboxChecked"
@
input=
"$emit('checked-input', $event)"
/>
<gl-filtered-search
ref=
"filteredSearchInput"
v-model=
"filterValue"
...
...
spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js
0 → 100644
View file @
6fbd2c64
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
IssuableBulkEditSidebar
from
'
~/issuable_list/components/issuable_bulk_edit_sidebar.vue
'
;
const
createComponent
=
({
expanded
=
true
}
=
{})
=>
shallowMount
(
IssuableBulkEditSidebar
,
{
propsData
:
{
expanded
,
},
slots
:
{
'
bulk-edit-actions
'
:
`
<button class="js-edit-issuables">Edit issuables</button>
`
,
'
sidebar-items
'
:
`
<button class="js-sidebar-dropdown">Labels</button>
`
,
},
});
describe
(
'
IssuableBulkEditSidebar
'
,
()
=>
{
let
wrapper
;
beforeEach
(()
=>
{
setFixtures
(
'
<div class="layout-page right-sidebar-collapsed"></div>
'
);
wrapper
=
createComponent
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
watch
'
,
()
=>
{
describe
(
'
expanded
'
,
()
=>
{
it
.
each
`
expanded | layoutPageClass
${
true
}
|
${
'
right-sidebar-expanded
'
}
${
false
}
|
${
'
right-sidebar-collapsed
'
}
`
(
'
sets class "$layoutPageClass" on element `.layout-page` when expanded prop is $expanded
'
,
async
({
expanded
,
layoutPageClass
})
=>
{
const
wrappeCustom
=
createComponent
({
expanded
:
!
expanded
,
});
// We need to manually flip the value of `expanded` for
// watcher to trigger.
wrappeCustom
.
setProps
({
expanded
,
});
await
wrappeCustom
.
vm
.
$nextTick
();
expect
(
document
.
querySelector
(
'
.layout-page
'
).
classList
.
contains
(
layoutPageClass
)).
toBe
(
true
,
);
wrappeCustom
.
destroy
();
},
);
});
});
describe
(
'
template
'
,
()
=>
{
it
.
each
`
expanded | layoutPageClass
${
true
}
|
${
'
right-sidebar-expanded
'
}
${
false
}
|
${
'
right-sidebar-collapsed
'
}
`
(
'
renders component container with class "$layoutPageClass" when expanded prop is $expanded
'
,
async
({
expanded
,
layoutPageClass
})
=>
{
const
wrappeCustom
=
createComponent
({
expanded
:
!
expanded
,
});
// We need to manually flip the value of `expanded` for
// watcher to trigger.
wrappeCustom
.
setProps
({
expanded
,
});
await
wrappeCustom
.
vm
.
$nextTick
();
expect
(
wrappeCustom
.
classes
()).
toContain
(
layoutPageClass
);
wrappeCustom
.
destroy
();
},
);
it
(
'
renders contents for slot `bulk-edit-actions`
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
button.js-edit-issuables
'
).
exists
()).
toBe
(
true
);
});
it
(
'
renders contents for slot `sidebar-items`
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
button.js-sidebar-dropdown
'
).
exists
()).
toBe
(
true
);
});
});
});
spec/frontend/issuable_list/components/issuable_item_spec.js
View file @
6fbd2c64
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlLink
,
GlLabel
}
from
'
@gitlab/ui
'
;
import
{
GlLink
,
GlLabel
,
GlFormCheckbox
}
from
'
@gitlab/ui
'
;
import
IssuableItem
from
'
~/issuable_list/components/issuable_item.vue
'
;
import
IssuableAssignees
from
'
~/vue_shared/components/issue/issue_assignees.vue
'
;
...
...
@@ -12,6 +12,7 @@ const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots
issuableSymbol
,
issuable
,
enableLabelPermalinks
:
true
,
showCheckbox
:
false
,
},
slots
,
});
...
...
@@ -196,6 +197,25 @@ describe('IssuableItem', () => {
expect
(
titleEl
.
find
(
GlLink
).
text
()).
toBe
(
mockIssuable
.
title
);
});
it
(
'
renders checkbox when `showCheckbox` prop is true
'
,
async
()
=>
{
wrapper
.
setProps
({
showCheckbox
:
true
,
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
find
(
GlFormCheckbox
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
GlFormCheckbox
).
attributes
(
'
checked
'
)).
not
.
toBeDefined
();
wrapper
.
setProps
({
checked
:
true
,
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
find
(
GlFormCheckbox
).
attributes
(
'
checked
'
)).
toBe
(
'
true
'
);
});
it
(
'
renders issuable title with `target` set as "_blank" when issuable.webUrl is external
'
,
async
()
=>
{
wrapper
.
setProps
({
issuable
:
{
...
...
spec/frontend/issuable_list/components/issuable_list_root_spec.js
View file @
6fbd2c64
...
...
@@ -8,11 +8,14 @@ import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
import
IssuableItem
from
'
~/issuable_list/components/issuable_item.vue
'
;
import
FilteredSearchBar
from
'
~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
'
;
import
{
mockIssuableListProps
}
from
'
../mock_data
'
;
import
{
mockIssuableListProps
,
mockIssuables
}
from
'
../mock_data
'
;
const
createComponent
=
(
propsData
=
mockIssuableListProps
)
=>
const
createComponent
=
(
{
props
=
mockIssuableListProps
,
data
=
{}
}
=
{}
)
=>
mount
(
IssuableListRoot
,
{
propsData
,
propsData
:
props
,
data
()
{
return
data
;
},
slots
:
{
'
nav-actions
'
:
`
<button class="js-new-issuable">New issuable</button>
...
...
@@ -35,6 +38,14 @@ describe('IssuableListRoot', () => {
});
describe
(
'
computed
'
,
()
=>
{
const
mockCheckedIssuables
=
{
[
mockIssuables
[
0
].
iid
]:
{
checked
:
true
,
issuable
:
mockIssuables
[
0
]
},
[
mockIssuables
[
1
].
iid
]:
{
checked
:
true
,
issuable
:
mockIssuables
[
1
]
},
[
mockIssuables
[
2
].
iid
]:
{
checked
:
true
,
issuable
:
mockIssuables
[
2
]
},
};
const
mIssuables
=
[
mockIssuables
[
0
],
mockIssuables
[
1
],
mockIssuables
[
2
]];
describe
(
'
skeletonItemCount
'
,
()
=>
{
it
.
each
`
totalItems | defaultPageSize | currentPage | returnValue
...
...
@@ -57,9 +68,62 @@ describe('IssuableListRoot', () => {
},
);
});
describe
(
'
allIssuablesChecked
'
,
()
=>
{
it
.
each
`
checkedIssuables | issuables | specTitle | returnValue
${
mockCheckedIssuables
}
|
${
mIssuables
}
|
${
'
same as
'
}
|
${
true
}
${{}}
|
$
{
mIssuables
}
|
${
'
not same as
'
}
|
${
false
}
`
(
'
returns $returnValue when bulkEditIssuables count is $specTitle issuables count
'
,
async
({
checkedIssuables
,
issuables
,
returnValue
})
=>
{
wrapper
.
setProps
({
issuables
,
});
await
wrapper
.
vm
.
$nextTick
();
wrapper
.
setData
({
checkedIssuables
,
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
vm
.
allIssuablesChecked
).
toBe
(
returnValue
);
},
);
});
describe
(
'
bulkEditIssuables
'
,
()
=>
{
it
(
'
returns array of issuables which have `checked` set to true within checkedIssuables map
'
,
async
()
=>
{
wrapper
.
setData
({
checkedIssuables
:
mockCheckedIssuables
,
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
vm
.
bulkEditIssuables
).
toHaveLength
(
mIssuables
.
length
);
});
});
});
describe
(
'
watch
'
,
()
=>
{
describe
(
'
issuables
'
,
()
=>
{
it
(
'
populates `checkedIssuables` prop with all issuables
'
,
async
()
=>
{
wrapper
.
setProps
({
issuables
:
[
mockIssuables
[
0
]],
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
Object
.
keys
(
wrapper
.
vm
.
checkedIssuables
)).
toHaveLength
(
1
);
expect
(
wrapper
.
vm
.
checkedIssuables
[
mockIssuables
[
0
].
iid
]).
toEqual
({
checked
:
false
,
issuable
:
mockIssuables
[
0
],
});
});
});
describe
(
'
urlParams
'
,
()
=>
{
it
(
'
updates window URL reflecting props within `urlParams`
'
,
async
()
=>
{
const
urlParams
=
{
...
...
@@ -82,6 +146,30 @@ describe('IssuableListRoot', () => {
});
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
issuableId
'
,
()
=>
{
it
(
'
returns id value from provided issuable object
'
,
()
=>
{
expect
(
wrapper
.
vm
.
issuableId
({
id
:
1
})).
toBe
(
1
);
expect
(
wrapper
.
vm
.
issuableId
({
iid
:
1
})).
toBe
(
1
);
expect
(
wrapper
.
vm
.
issuableId
({})).
toBeDefined
();
});
});
describe
(
'
issuableChecked
'
,
()
=>
{
it
(
'
returns boolean value representing checked status of issuable item
'
,
async
()
=>
{
wrapper
.
setData
({
checkedIssuables
:
{
[
mockIssuables
[
0
].
iid
]:
{
checked
:
true
,
issuable
:
mockIssuables
[
0
]
},
},
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
vm
.
issuableChecked
(
mockIssuables
[
0
])).
toBe
(
true
);
});
});
});
describe
(
'
template
'
,
()
=>
{
it
(
'
renders component container element with class "issuable-list-container"
'
,
()
=>
{
expect
(
wrapper
.
classes
()).
toContain
(
'
issuable-list-container
'
);
...
...
@@ -183,12 +271,44 @@ describe('IssuableListRoot', () => {
});
describe
(
'
events
'
,
()
=>
{
let
wrapperChecked
;
beforeEach
(()
=>
{
wrapperChecked
=
createComponent
({
data
:
{
checkedIssuables
:
{
[
mockIssuables
[
0
].
iid
]:
{
checked
:
true
,
issuable
:
mockIssuables
[
0
]
},
},
},
});
});
afterEach
(()
=>
{
wrapperChecked
.
destroy
();
});
it
(
'
issuable-tabs component emits `click-tab` event on `click-tab` event
'
,
()
=>
{
wrapper
.
find
(
IssuableTabs
).
vm
.
$emit
(
'
click
'
);
expect
(
wrapper
.
emitted
(
'
click-tab
'
)).
toBeTruthy
();
});
it
(
'
sets all issuables as checked when filtered-search-bar component emits `checked-input` event
'
,
async
()
=>
{
const
searchEl
=
wrapperChecked
.
find
(
FilteredSearchBar
);
searchEl
.
vm
.
$emit
(
'
checked-input
'
,
true
);
await
wrapperChecked
.
vm
.
$nextTick
();
expect
(
searchEl
.
emitted
(
'
checked-input
'
)).
toBeTruthy
();
expect
(
searchEl
.
emitted
(
'
checked-input
'
).
length
).
toBe
(
1
);
expect
(
wrapperChecked
.
vm
.
checkedIssuables
[
mockIssuables
[
0
].
iid
]).
toEqual
({
checked
:
true
,
issuable
:
mockIssuables
[
0
],
});
});
it
(
'
filtered-search-bar component emits `filter` event on `onFilter` & `sort` event on `onSort` events
'
,
()
=>
{
const
searchEl
=
wrapper
.
find
(
FilteredSearchBar
);
...
...
@@ -198,6 +318,22 @@ describe('IssuableListRoot', () => {
expect
(
wrapper
.
emitted
(
'
sort
'
)).
toBeTruthy
();
});
it
(
'
sets an issuable as checked when issuable-item component emits `checked-input` event
'
,
async
()
=>
{
const
issuableItem
=
wrapperChecked
.
findAll
(
IssuableItem
).
at
(
0
);
issuableItem
.
vm
.
$emit
(
'
checked-input
'
,
true
);
await
wrapperChecked
.
vm
.
$nextTick
();
expect
(
issuableItem
.
emitted
(
'
checked-input
'
)).
toBeTruthy
();
expect
(
issuableItem
.
emitted
(
'
checked-input
'
).
length
).
toBe
(
1
);
expect
(
wrapperChecked
.
vm
.
checkedIssuables
[
mockIssuables
[
0
].
iid
]).
toEqual
({
checked
:
true
,
issuable
:
mockIssuables
[
0
],
});
});
it
(
'
gl-pagination component emits `page-change` event on `input` event
'
,
async
()
=>
{
wrapper
.
setProps
({
showPaginationControls
:
true
,
...
...
spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
View file @
6fbd2c64
import
{
shallowMount
,
mount
}
from
'
@vue/test-utils
'
;
import
{
GlFilteredSearch
,
GlButtonGroup
,
GlButton
,
GlDropdown
,
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
GlFilteredSearch
,
GlButtonGroup
,
GlButton
,
GlDropdown
,
GlDropdownItem
,
GlFormCheckbox
,
}
from
'
@gitlab/ui
'
;
import
FilteredSearchBarRoot
from
'
~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
'
;
import
{
uniqueTokens
}
from
'
~/vue_shared/components/filtered_search_bar/filtered_search_utils
'
;
...
...
@@ -30,6 +37,8 @@ const createComponent = ({
recentSearchesStorageKey
=
'
requirements
'
,
tokens
=
mockAvailableTokens
,
sortOptions
,
showCheckbox
=
false
,
checkboxChecked
=
false
,
searchInputPlaceholder
=
'
Filter requirements
'
,
}
=
{})
=>
{
const
mountMethod
=
shallow
?
shallowMount
:
mount
;
...
...
@@ -40,6 +49,8 @@ const createComponent = ({
recentSearchesStorageKey
,
tokens
,
sortOptions
,
showCheckbox
,
checkboxChecked
,
searchInputPlaceholder
,
},
});
...
...
@@ -364,6 +375,26 @@ describe('FilteredSearchBarRoot', () => {
expect
(
glFilteredSearchEl
.
props
(
'
historyItems
'
)).
toEqual
(
mockHistoryItems
);
});
it
(
'
renders checkbox when `showCheckbox` prop is true
'
,
async
()
=>
{
let
wrapperWithCheckbox
=
createComponent
({
showCheckbox
:
true
,
});
expect
(
wrapperWithCheckbox
.
find
(
GlFormCheckbox
).
exists
()).
toBe
(
true
);
expect
(
wrapperWithCheckbox
.
find
(
GlFormCheckbox
).
attributes
(
'
checked
'
)).
not
.
toBeDefined
();
wrapperWithCheckbox
.
destroy
();
wrapperWithCheckbox
=
createComponent
({
showCheckbox
:
true
,
checkboxChecked
:
true
,
});
expect
(
wrapperWithCheckbox
.
find
(
GlFormCheckbox
).
attributes
(
'
checked
'
)).
toBe
(
'
true
'
);
wrapperWithCheckbox
.
destroy
();
});
it
(
'
renders search history items dropdown with formatting done using token symbols
'
,
async
()
=>
{
const
wrapperFullMount
=
createComponent
({
sortOptions
:
mockSortOptions
,
shallow
:
false
});
wrapperFullMount
.
vm
.
recentSearchesStore
.
addRecentSearch
(
mockHistoryItems
[
0
]);
...
...
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