Alerting: Fix AlertLabelDropdown to be case sensitive (#63787)

Fix AlertLabelDropdown to be case sensitive
This commit is contained in:
Sonia Aguilar 2023-02-28 09:53:33 +01:00 committed by GitHub
parent e4d72df758
commit 526cac60e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 4 deletions

View File

@ -181,7 +181,7 @@ export function SelectBase<T>({
let ReactSelectComponent = ReactSelect; let ReactSelectComponent = ReactSelect;
const creatableProps: ComponentProps<typeof Creatable> = {}; const creatableProps: ComponentProps<typeof Creatable<SelectableValue<T>>> = {};
let asyncSelectProps: any = {}; let asyncSelectProps: any = {};
let selectedValue; let selectedValue;
if (isMulti && loadOptions) { if (isMulti && loadOptions) {

View File

@ -88,7 +88,7 @@ export interface SelectCommonProps<T> {
isValidNewOption?: ( isValidNewOption?: (
inputValue: string, inputValue: string,
value: SelectableValue<T> | null, value: SelectableValue<T> | null,
options: OptionsOrGroups<unknown, GroupBase<unknown>> options: OptionsOrGroups<SelectableValue<T>, GroupBase<SelectableValue<T>>>
) => boolean; ) => boolean;
/** Message to display isLoading=true*/ /** Message to display isLoading=true*/
loadingMessage?: string; loadingMessage?: string;

View File

@ -1,7 +1,8 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { createFilter, GroupBase, OptionsOrGroups } from 'react-select';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
import { Select, Field } from '@grafana/ui'; import { Field, Select } from '@grafana/ui';
export interface AlertLabelDropdownProps { export interface AlertLabelDropdownProps {
onChange: (newValue: SelectableValue<string>) => void; onChange: (newValue: SelectableValue<string>) => void;
@ -10,19 +11,42 @@ export interface AlertLabelDropdownProps {
defaultValue?: SelectableValue; defaultValue?: SelectableValue;
type: 'key' | 'value'; type: 'key' | 'value';
} }
const _customFilter = createFilter({ ignoreCase: false });
function customFilter(opt: SelectableValue, searchQuery: string) {
return _customFilter(
{
label: opt.label ?? '',
value: opt.value ?? '',
data: {},
},
searchQuery
);
}
const handleIsValidNewOption = (
inputValue: string,
value: SelectableValue<string> | null,
options: OptionsOrGroups<SelectableValue<string>, GroupBase<SelectableValue<string>>>
) => {
const exactValueExists = options.some((el) => el.label === inputValue);
const valueIsNotEmpty = inputValue.trim().length;
return !Boolean(exactValueExists) && Boolean(valueIsNotEmpty);
};
const AlertLabelDropdown: FC<AlertLabelDropdownProps> = React.forwardRef<HTMLDivElement, AlertLabelDropdownProps>( const AlertLabelDropdown: FC<AlertLabelDropdownProps> = React.forwardRef<HTMLDivElement, AlertLabelDropdownProps>(
function labelPicker({ onChange, options, defaultValue, type, onOpenMenu = () => {} }, ref) { function labelPicker({ onChange, options, defaultValue, type, onOpenMenu = () => {} }, ref) {
return ( return (
<div ref={ref}> <div ref={ref}>
<Field disabled={false} data-testid={`alertlabel-${type}-picker`}> <Field disabled={false} data-testid={`alertlabel-${type}-picker`}>
<Select <Select<string>
placeholder={`Choose ${type}`} placeholder={`Choose ${type}`}
width={29} width={29}
className="ds-picker select-container" className="ds-picker select-container"
backspaceRemovesValue={false} backspaceRemovesValue={false}
onChange={onChange} onChange={onChange}
onOpenMenu={onOpenMenu} onOpenMenu={onOpenMenu}
filterOption={customFilter}
isValidNewOption={handleIsValidNewOption}
options={options} options={options}
maxMenuHeight={500} maxMenuHeight={500}
noOptionsMessage="No labels found" noOptionsMessage="No labels found"

View File

@ -92,6 +92,26 @@ describe('LabelsField with suggestions', () => {
expect(screen.getByTestId('label-key-2').textContent).toBe('key3'); expect(screen.getByTestId('label-key-2').textContent).toBe('key3');
expect(screen.getByTestId('label-value-2').textContent).toBe('value3'); expect(screen.getByTestId('label-value-2').textContent).toBe('value3');
}); });
it('Should be able to write new keys and values using the dropdowns, case sensitive', async () => {
renderAlertLabels('grafana');
await waitFor(() => expect(screen.getAllByTestId('alertlabel-key-picker')).toHaveLength(2));
expect(screen.getByTestId('label-key-0').textContent).toBe('key1');
expect(screen.getByTestId('label-key-1').textContent).toBe('key2');
expect(screen.getByTestId('label-value-0').textContent).toBe('value1');
expect(screen.getByTestId('label-value-1').textContent).toBe('value2');
const LastKeyDropdown = within(screen.getByTestId('label-key-1'));
const LastValueDropdown = within(screen.getByTestId('label-value-1'));
await userEvent.type(LastKeyDropdown.getByRole('combobox'), 'KEY2{enter}');
expect(screen.getByTestId('label-key-0').textContent).toBe('key1');
expect(screen.getByTestId('label-key-1').textContent).toBe('KEY2');
await userEvent.type(LastValueDropdown.getByRole('combobox'), 'VALUE2{enter}');
expect(screen.getByTestId('label-value-0').textContent).toBe('value1');
expect(screen.getByTestId('label-value-1').textContent).toBe('VALUE2');
});
}); });
describe('LabelsField without suggestions', () => { describe('LabelsField without suggestions', () => {