Commit 8188d09f authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'ps-fix-search-term-case-sensitivity-namespace-select' into 'master'

Fix search term case sensitivity for transfer namespace

See merge request gitlab-org/gitlab!79595
parents 36d22a85 d8256211
...@@ -43,9 +43,6 @@ export default { ...@@ -43,9 +43,6 @@ export default {
}; };
}, },
computed: { computed: {
selectedNamespaceId() {
return this.selectedId;
},
disableSubmitButton() { disableSubmitButton() {
return this.isPaidGroup || !this.selectedId; return this.isPaidGroup || !this.selectedId;
}, },
......
...@@ -4,6 +4,10 @@ import { parseBoolean } from '~/lib/utils/common_utils'; ...@@ -4,6 +4,10 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import TransferGroupForm, { i18n } from './components/transfer_group_form.vue'; import TransferGroupForm, { i18n } from './components/transfer_group_form.vue';
const prepareGroups = (rawGroups) => { const prepareGroups = (rawGroups) => {
if (!rawGroups) {
return { group: [] };
}
const group = JSON.parse(rawGroups).map(({ id, text: humanName }) => ({ const group = JSON.parse(rawGroups).map(({ id, text: humanName }) => ({
id, id,
humanName, humanName,
...@@ -22,7 +26,7 @@ export default () => { ...@@ -22,7 +26,7 @@ export default () => {
targetFormId = null, targetFormId = null,
buttonText: confirmButtonText = '', buttonText: confirmButtonText = '',
groupName = '', groupName = '',
parentGroups = [], parentGroups,
isPaidGroup, isPaidGroup,
} = el.dataset; } = el.dataset;
......
...@@ -16,8 +16,13 @@ export const i18n = { ...@@ -16,8 +16,13 @@ export const i18n = {
USERS: __('Users'), USERS: __('Users'),
}; };
const filterByName = (data, searchTerm = '') => const filterByName = (data, searchTerm = '') => {
data.filter((d) => d.humanName.toLowerCase().includes(searchTerm)); if (!searchTerm) {
return data;
}
return data.filter((d) => d.humanName.toLowerCase().includes(searchTerm.toLowerCase()));
};
export default { export default {
name: 'NamespaceSelect', name: 'NamespaceSelect',
...@@ -85,7 +90,15 @@ export default { ...@@ -85,7 +90,15 @@ export default {
}, },
filteredEmptyNamespaceTitle() { filteredEmptyNamespaceTitle() {
const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this; const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this;
return includeEmptyNamespace && emptyNamespaceTitle.toLowerCase().includes(searchTerm);
if (!includeEmptyNamespace) {
return '';
}
if (!searchTerm) {
return emptyNamespaceTitle;
}
return emptyNamespaceTitle.toLowerCase().includes(searchTerm.toLowerCase());
}, },
}, },
methods: { methods: {
......
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader } from '@gitlab/ui'; import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import NamespaceSelect, { import NamespaceSelect, {
i18n, i18n,
...@@ -7,6 +7,10 @@ import NamespaceSelect, { ...@@ -7,6 +7,10 @@ import NamespaceSelect, {
} from '~/vue_shared/components/namespace_select/namespace_select.vue'; } from '~/vue_shared/components/namespace_select/namespace_select.vue';
import { user, group, namespaces } from './mock_data'; import { user, group, namespaces } from './mock_data';
const FLAT_NAMESPACES = [...group, ...user];
const EMPTY_NAMESPACE_TITLE = 'Empty namespace TEST';
const EMPTY_NAMESPACE_ITEM = { id: EMPTY_NAMESPACE_ID, humanName: EMPTY_NAMESPACE_TITLE };
describe('Namespace Select', () => { describe('Namespace Select', () => {
let wrapper; let wrapper;
...@@ -16,67 +20,97 @@ describe('Namespace Select', () => { ...@@ -16,67 +20,97 @@ describe('Namespace Select', () => {
data: namespaces, data: namespaces,
...props, ...props,
}, },
stubs: {
// We have to "full" mount GlDropdown so that slot children will render
GlDropdown,
},
}); });
const wrappersText = (arr) => arr.wrappers.map((w) => w.text()); const wrappersText = (arr) => arr.wrappers.map((w) => w.text());
const flatNamespaces = () => [...group, ...user];
const findDropdown = () => wrapper.findComponent(GlDropdown); const findDropdown = () => wrapper.findComponent(GlDropdown);
const findDropdownAttributes = (attr) => findDropdown().attributes(attr); const findDropdownText = () => findDropdown().props('text');
const selectedDropdownItemText = () => findDropdownAttributes('text');
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findDropdownItemsTexts = () => findDropdownItems().wrappers.map((x) => x.text());
const findSectionHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader); const findSectionHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader);
const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
beforeEach(() => { const search = (term) => findSearchBox().vm.$emit('input', term);
wrapper = createComponent();
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders the dropdown', () => { describe('default', () => {
expect(findDropdown().exists()).toBe(true); beforeEach(() => {
}); wrapper = createComponent();
});
it('can override the default text', () => { it('renders the dropdown', () => {
const textOverride = 'Select an option'; expect(findDropdown().exists()).toBe(true);
wrapper = createComponent({ defaultText: textOverride }); });
expect(selectedDropdownItemText()).toBe(textOverride);
});
it('renders each dropdown item', () => { it('renders each dropdown item', () => {
const items = findDropdownItems().wrappers; expect(findDropdownItemsTexts()).toEqual(FLAT_NAMESPACES.map((x) => x.humanName));
expect(items).toHaveLength(flatNamespaces().length); });
});
it('renders the human name for each item', () => { it('renders default dropdown text', () => {
const dropdownItems = wrappersText(findDropdownItems()); expect(findDropdownText()).toBe(i18n.DEFAULT_TEXT);
const flatNames = flatNamespaces().map(({ humanName }) => humanName); });
expect(dropdownItems).toEqual(flatNames);
});
it('sets the initial dropdown text', () => { it('splits group and user namespaces', () => {
expect(selectedDropdownItemText()).toBe(i18n.DEFAULT_TEXT); const headers = findSectionHeaders();
expect(wrappersText(headers)).toEqual([i18n.GROUPS, i18n.USERS]);
});
it('does not render wrapper as full width', () => {
expect(findDropdown().attributes('block')).toBeUndefined();
});
}); });
it('splits group and user namespaces', () => { it('with defaultText, it overrides dropdown text', () => {
const headers = findSectionHeaders(); const textOverride = 'Select an option';
expect(headers).toHaveLength(2);
expect(wrappersText(headers)).toEqual([i18n.GROUPS, i18n.USERS]); wrapper = createComponent({ defaultText: textOverride });
expect(findDropdownText()).toBe(textOverride);
}); });
it('can hide the group / user headers', () => { it('with includeHeaders=false, hides group/user headers', () => {
wrapper = createComponent({ includeHeaders: false }); wrapper = createComponent({ includeHeaders: false });
expect(findSectionHeaders()).toHaveLength(0); expect(findSectionHeaders()).toHaveLength(0);
}); });
it('sets the dropdown to full width', () => { it('with fullWidth=true, sets the dropdown to full width', () => {
expect(findDropdownAttributes('block')).toBeUndefined();
wrapper = createComponent({ fullWidth: true }); wrapper = createComponent({ fullWidth: true });
expect(findDropdownAttributes('block')).not.toBeUndefined(); expect(findDropdown().attributes('block')).toBe('true');
expect(findDropdownAttributes('block')).toBe('true'); });
describe('with search', () => {
it.each`
term | includeEmptyNamespace | expectedItems
${''} | ${false} | ${[...namespaces.group, ...namespaces.user]}
${'sub'} | ${false} | ${[namespaces.group[1]]}
${'User'} | ${false} | ${[...namespaces.user]}
${'User'} | ${true} | ${[...namespaces.user]}
${'namespace'} | ${true} | ${[EMPTY_NAMESPACE_ITEM, ...namespaces.user]}
`(
'with term=$term and includeEmptyNamespace=$includeEmptyNamespace, should show $expectedItems.length',
async ({ term, includeEmptyNamespace, expectedItems }) => {
wrapper = createComponent({
includeEmptyNamespace,
emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
});
search(term);
await nextTick();
const expected = expectedItems.map((x) => x.humanName);
expect(findDropdownItemsTexts()).toEqual(expected);
},
);
}); });
describe('with a selected namespace', () => { describe('with a selected namespace', () => {
...@@ -84,11 +118,13 @@ describe('Namespace Select', () => { ...@@ -84,11 +118,13 @@ describe('Namespace Select', () => {
const selectedItem = group[selectedGroupIndex]; const selectedItem = group[selectedGroupIndex];
beforeEach(() => { beforeEach(() => {
wrapper = createComponent();
findDropdownItems().at(selectedGroupIndex).vm.$emit('click'); findDropdownItems().at(selectedGroupIndex).vm.$emit('click');
}); });
it('sets the dropdown text', () => { it('sets the dropdown text', () => {
expect(selectedDropdownItemText()).toBe(selectedItem.humanName); expect(findDropdownText()).toBe(selectedItem.humanName);
}); });
it('emits the `select` event when a namespace is selected', () => { it('emits the `select` event when a namespace is selected', () => {
...@@ -98,27 +134,35 @@ describe('Namespace Select', () => { ...@@ -98,27 +134,35 @@ describe('Namespace Select', () => {
}); });
describe('with an empty namespace option', () => { describe('with an empty namespace option', () => {
const emptyNamespaceTitle = 'No namespace selected'; beforeEach(() => {
beforeEach(async () => {
wrapper = createComponent({ wrapper = createComponent({
includeEmptyNamespace: true, includeEmptyNamespace: true,
emptyNamespaceTitle, emptyNamespaceTitle: EMPTY_NAMESPACE_TITLE,
}); });
await nextTick();
}); });
it('includes the empty namespace', () => { it('includes the empty namespace', () => {
const first = findDropdownItems().at(0); const first = findDropdownItems().at(0);
expect(first.text()).toBe(emptyNamespaceTitle);
expect(first.text()).toBe(EMPTY_NAMESPACE_TITLE);
}); });
it('emits the `select` event when a namespace is selected', () => { it('emits the `select` event when a namespace is selected', () => {
findDropdownItems().at(0).vm.$emit('click'); findDropdownItems().at(0).vm.$emit('click');
expect(wrapper.emitted('select')).toEqual([ expect(wrapper.emitted('select')).toEqual([[EMPTY_NAMESPACE_ITEM]]);
[{ id: EMPTY_NAMESPACE_ID, humanName: emptyNamespaceTitle }], });
]);
it.each`
desc | term | shouldShow
${'should hide empty option'} | ${'group'} | ${false}
${'should show empty option'} | ${'Empty'} | ${true}
`('when search for $term, $desc', async ({ term, shouldShow }) => {
search(term);
await nextTick();
expect(findDropdownItemsTexts().includes(EMPTY_NAMESPACE_TITLE)).toBe(shouldShow);
}); });
}); });
}); });
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