diff --git a/src/web/components/form/__tests__/select.jsx b/src/web/components/form/__tests__/select.jsx index 396feb1a69..67a201a0eb 100644 --- a/src/web/components/form/__tests__/select.jsx +++ b/src/web/components/form/__tests__/select.jsx @@ -26,7 +26,7 @@ import { clickElement, } from 'web/components/testing'; -import Select from '../select'; +import Select, {SelectItem} from '../select'; describe('Select component tests', () => { test('should render', () => { @@ -229,6 +229,26 @@ describe('Select component tests', () => { expect(getSelectItemElements().length).toEqual(1); }); + describe('SelectItemRaw', () => { + test.each([ + { + label: 'Test Item', + deprecated: '1', + expectedText: 'Test Item (Deprecated)', + }, + { + label: 'Non-deprecated Item', + deprecated: undefined, + expectedText: 'Non-deprecated Item', + }, + ])( + 'renders $label correctly with deprecated status $deprecated', + ({label, deprecated, expectedText}) => { + const {getByText} = render( + , + ); + expect(getByText(expectedText)).toBeInTheDocument(); + }, + ); + }); }); - -// vim: set ts=2 sw=2 tw=80: diff --git a/src/web/components/form/select.jsx b/src/web/components/form/select.jsx index 714a8a67ec..6dfd749b09 100644 --- a/src/web/components/form/select.jsx +++ b/src/web/components/form/select.jsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import {useCallback} from 'react'; +import {useCallback, forwardRef} from 'react'; import {Loader} from '@mantine/core'; @@ -28,6 +28,8 @@ import PropTypes, {mayRequire} from 'web/utils/proptypes'; import useTranslation from 'web/hooks/useTranslation'; +import {_} from 'gmp/locale/lang'; + const findItem = (items, value) => isDefined(items) ? items.find(i => i.value === value) : undefined; @@ -72,6 +74,24 @@ const SelectValueValidator = (props, propName, componentName) => { const selectValue = mayRequire(SelectValueValidator); +const renderLabel = props => { + const {label, deprecated} = props; + + if (deprecated) { + return {`${label} (${_('Deprecated')})`}; + } + + return {label}; +}; + +export const SelectItem = forwardRef((props, ref) => { + return ( +
+ {renderLabel(props)} +
+ ); +}); + const Select = ({ disabled, dropdownPosition, @@ -120,6 +140,7 @@ const Select = ({ value={selectedValue} onChange={handleChange} rightSection={rightSection} + itemComponent={SelectItem} /> ); }; diff --git a/src/web/utils/__tests__/render.jsx b/src/web/utils/__tests__/render.jsx index 3ed1d74ab4..4d32a4edaf 100644 --- a/src/web/utils/__tests__/render.jsx +++ b/src/web/utils/__tests__/render.jsx @@ -39,31 +39,6 @@ describe('render_select_items test', () => { expect(items[1]).toEqual({label: 'B Task', value: '2'}); }); - test('should mark deprecated items', () => { - const entities = [ - { - name: 'A Config', - id: '1', - }, - { - name: 'B Config', - deprecated: '1', - id: '2', - }, - { - name: 'C Config', - id: '3', - }, - ]; - - const items = renderSelectItems(entities); - - expect(items.length).toBe(3); - expect(items[0]).toEqual({label: 'A Config', value: '1'}); - expect(items[1]).toEqual({label: B Config (Deprecated), value: '2'}); - expect(items[2]).toEqual({label: 'C Config', value: '3'}); - }); - test('should add default item', () => { const entities = [ { @@ -103,6 +78,26 @@ describe('render_select_items test', () => { expect(items[1]).toEqual({label: 'A Task', value: '1'}); expect(items[2]).toEqual({label: 'B Task', value: '2'}); }); + + test.each([ + {name: 'Item 1', id: 1, deprecated: '1'}, + {name: 'Item 2', id: 2}, + {name: 123, id: 3, deprecated: '1'}, + {name: true, id: 4}, + {name: null, id: 5}, + {name: undefined, id: 6}, + ])('should return labels as strings for item with id %s', item => { + const default_item_value = 0; + const default_item_label = 'Default Item'; + + const result = renderSelectItems( + [item], + default_item_value, + default_item_label, + ); + + expect(typeof result[1].label).toBe('string'); + }); }); describe('generateFilename tests', () => { diff --git a/src/web/utils/render.jsx b/src/web/utils/render.jsx index 972329f704..9d1a967e8d 100644 --- a/src/web/utils/render.jsx +++ b/src/web/utils/render.jsx @@ -30,14 +30,6 @@ import {typeName, getEntityType} from 'gmp/utils/entitytype'; export const UNSET_VALUE = '0'; export const UNSET_LABEL = '--'; -function selectItemLabel(item) { - const itemText = isDefined(item.name) ? item.name : item.id; - if (item.deprecated) { - return {itemText + ' (' + _('Deprecated') + ')'}; - } - return itemText; -} - /** * Render a entities list as items array * @@ -53,7 +45,11 @@ export const renderSelectItems = ( default_item_label = UNSET_LABEL, ) => { const items = isDefined(list) - ? list.map(item => ({label: selectItemLabel(item), value: item.id})) + ? list.map(item => ({ + label: String(item.name), + value: item.id, + deprecated: item.deprecated, + })) : undefined; if (!isDefined(default_item_value)) {