Commit e93b6138 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '284471-focus-filter-search-on-dropdown-open' into 'master'

Improve search box for filter dropdowns on vulnerability page

See merge request gitlab-org/gitlab!55159
parents 5599a664 2a55c81c
...@@ -44,6 +44,12 @@ export default { ...@@ -44,6 +44,12 @@ export default {
emitInput(value) { emitInput(value) {
this.$emit('input', value); this.$emit('input', value);
}, },
async emitDropdownShow() {
this.$emit('dropdown-show');
// Focus on the search box when the dropdown is opened.
await this.$nextTick();
this.$refs.searchBox?.focusInput();
},
}, },
}; };
</script> </script>
...@@ -56,6 +62,8 @@ export default { ...@@ -56,6 +62,8 @@ export default {
menu-class="dropdown-extended-height" menu-class="dropdown-extended-height"
:header-text="name" :header-text="name"
toggle-class="gl-w-full" toggle-class="gl-w-full"
@show="emitDropdownShow"
@hide="$emit('dropdown-hide')"
> >
<template #button-content> <template #button-content>
<gl-truncate <gl-truncate
...@@ -69,11 +77,14 @@ export default { ...@@ -69,11 +77,14 @@ export default {
<gl-icon name="chevron-down" class="gl-flex-shrink-0 gl-ml-auto" /> <gl-icon name="chevron-down" class="gl-flex-shrink-0 gl-ml-auto" />
</template> </template>
<gl-search-box-by-type <template v-if="showSearchBox" #header>
v-if="showSearchBox" <gl-search-box-by-type
:placeholder="__('Filter...')" ref="searchBox"
@input="emitInput" :placeholder="__('Search')"
/> autocomplete="off"
@input="emitInput"
/>
</template>
<slot> <slot>
<gl-dropdown-text> <gl-dropdown-text>
......
...@@ -10,15 +10,16 @@ describe('Filter Body component', () => { ...@@ -10,15 +10,16 @@ describe('Filter Body component', () => {
selectedOptions: [], selectedOptions: [],
}; };
const createComponent = (props, slotContent = '') => { const createComponent = (props, options) => {
wrapper = mount(FilterBody, { wrapper = mount(FilterBody, {
propsData: { ...defaultProps, ...props }, propsData: { ...defaultProps, ...props },
slots: { default: slotContent }, ...options,
}); });
}; };
const dropdown = () => wrapper.findComponent(GlDropdown);
const dropdownButton = () => wrapper.find('.dropdown-toggle'); const dropdownButton = () => wrapper.find('.dropdown-toggle');
const searchBox = () => wrapper.find(GlSearchBoxByType); const searchBox = () => wrapper.findComponent(GlSearchBoxByType);
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
...@@ -28,7 +29,21 @@ describe('Filter Body component', () => { ...@@ -28,7 +29,21 @@ describe('Filter Body component', () => {
createComponent(); createComponent();
expect(wrapper.find('[data-testid="name"]').text()).toBe(defaultProps.name); expect(wrapper.find('[data-testid="name"]').text()).toBe(defaultProps.name);
expect(wrapper.find(GlDropdown).props('headerText')).toBe(defaultProps.name); expect(dropdown().props('headerText')).toBe(defaultProps.name);
});
it('emits dropdown-show event when dropdown is shown', () => {
createComponent();
dropdown().vm.$emit('show');
expect(wrapper.emitted('dropdown-show')).toHaveLength(1);
});
it('emits dropdown-hide event when dropdown is hidden', () => {
createComponent();
dropdown().vm.$emit('hide');
expect(wrapper.emitted('dropdown-hide')).toHaveLength(1);
}); });
describe('dropdown button', () => { describe('dropdown button', () => {
...@@ -56,6 +71,15 @@ describe('Filter Body component', () => { ...@@ -56,6 +71,15 @@ describe('Filter Body component', () => {
expect(searchBox().exists()).toBe(show); expect(searchBox().exists()).toBe(show);
}); });
it('is focused when the dropdown is opened', async () => {
createComponent({ showSearchBox: true }, { attachTo: document.body });
const spy = jest.spyOn(searchBox().vm, 'focusInput');
dropdown().vm.$emit('show');
await wrapper.vm.$nextTick();
expect(spy).toHaveBeenCalledTimes(1);
});
it('emits input event on component when search box input is changed', () => { it('emits input event on component when search box input is changed', () => {
const text = 'abc'; const text = 'abc';
createComponent({ showSearchBox: true }); createComponent({ showSearchBox: true });
...@@ -68,7 +92,7 @@ describe('Filter Body component', () => { ...@@ -68,7 +92,7 @@ describe('Filter Body component', () => {
describe('dropdown body', () => { describe('dropdown body', () => {
it('shows slot content', () => { it('shows slot content', () => {
const slotContent = 'some slot content'; const slotContent = 'some slot content';
createComponent({}, slotContent); createComponent({}, { slots: { default: slotContent } });
expect(wrapper.text()).toContain(slotContent); expect(wrapper.text()).toContain(slotContent);
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment