Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,50 +52,46 @@ describe('AutocompleteFieldListsComponent', () => {
selectedField={getField('ip')}
selectedValue="some-list-id"
isLoading={false}
isClearable={false}
isDisabled={true}
isClearable={true}
isDisabled
onChange={jest.fn()}
/>
</ThemeProvider>
);

await waitFor(() => {
expect(
wrapper
.find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] input`)
.prop('disabled')
).toBeTruthy();
});
expect(
wrapper
.find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] input`)
.prop('disabled')
).toBeTruthy();
});

test('it renders loading if "isLoading" is true', async () => {
const wrapper = mount(
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>
<AutocompleteFieldListsComponent
placeholder="Placeholder text"
selectedField={getField('ip')}
selectedValue="some-list-id"
isLoading={true}
selectedField={getField('@tags')}
selectedValue=""
isLoading
isClearable={false}
isDisabled={false}
onChange={jest.fn()}
/>
</ThemeProvider>
);

await waitFor(() => {
wrapper
.find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] button`)
.at(0)
.simulate('click');
expect(
wrapper
.find(`[data-test-subj="valuesAutocompleteComboBox listsComboxBox"] button`)
.at(0)
.simulate('click');
expect(
wrapper
.find(
`EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteComboBox listsComboxBox-optionsList"]`
)
.prop('isLoading')
).toBeTruthy();
});
.find(
`EuiComboBoxOptionsList[data-test-subj="valuesAutocompleteComboBox listsComboxBox-optionsList"]`
)
.prop('isLoading')
).toBeTruthy();
});

test('it allows user to clear values if "isClearable" is true', async () => {
Expand All @@ -104,19 +100,19 @@ describe('AutocompleteFieldListsComponent', () => {
<AutocompleteFieldListsComponent
placeholder="Placeholder text"
selectedField={getField('ip')}
selectedValue="some-list-id"
selectedValue=""
isLoading={false}
isClearable={true}
isClearable={false}
isDisabled={false}
onChange={jest.fn()}
/>
</ThemeProvider>
);
expect(
wrapper
.find(`[data-test-subj="comboBoxInput"]`)
.hasClass('euiComboBox__inputWrap-isClearable')
).toBeTruthy();
.find('EuiComboBox[data-test-subj="valuesAutocompleteComboBox listsComboxBox"]')
.prop('options')
).toEqual([{ label: 'some name' }]);
});

test('it correctly displays lists that match the selected "keyword" field esType', () => {
Expand Down Expand Up @@ -210,19 +206,24 @@ describe('AutocompleteFieldListsComponent', () => {
onChange: (a: EuiComboBoxOptionOption[]) => void;
}).onChange([{ label: 'some name' }]);

expect(mockOnChange).toHaveBeenCalledWith({
created_at: DATE_NOW,
created_by: 'some user',
description: 'some description',
id: 'some-list-id',
meta: {},
name: 'some name',
tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e',
type: 'ip',
updated_at: DATE_NOW,
updated_by: 'some user',
version: VERSION,
immutable: IMMUTABLE,
await waitFor(() => {
expect(mockOnChange).toHaveBeenCalledWith({
created_at: DATE_NOW,
created_by: 'some user',
description: 'some description',
id: 'some-list-id',
meta: {},
name: 'some name',
tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e',
type: 'ip',
updated_at: DATE_NOW,
updated_by: 'some user',
_version: undefined,
version: VERSION,
deserializer: undefined,
serializer: undefined,
immutable: IMMUTABLE,
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { EuiComboBoxOptionOption, EuiComboBox } from '@elastic/eui';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import { useFindLists, ListSchema } from '../../../lists_plugin_deps';
import { useKibana } from '../../../common/lib/kibana';
import { getGenericComboBoxProps } from './helpers';
import { getGenericComboBoxProps, paramIsValid } from './helpers';

interface AutocompleteFieldListsProps {
placeholder: string;
Expand Down Expand Up @@ -75,6 +75,8 @@ export const AutocompleteFieldListsComponent: React.FC<AutocompleteFieldListsPro
[labels, optionsMemo, onChange]
);

const setIsTouchedValue = useCallback(() => setIsTouched(true), [setIsTouched]);

useEffect(() => {
if (result != null) {
setLists(result.data);
Expand All @@ -91,17 +93,24 @@ export const AutocompleteFieldListsComponent: React.FC<AutocompleteFieldListsPro
}
}, [selectedField, start, http]);

const isValid = useMemo(
(): boolean => paramIsValid(selectedValue, selectedField, isRequired, touched),
[selectedField, selectedValue, isRequired, touched]
);

const isLoadingState = useMemo((): boolean => isLoading || loading, [isLoading, loading]);

return (
<EuiComboBox
placeholder={placeholder}
isDisabled={isDisabled}
isLoading={isLoading || loading}
isLoading={isLoadingState}
isClearable={isClearable}
options={comboOptions}
selectedOptions={selectedComboOptions}
onChange={handleValuesChange}
isInvalid={isRequired ? touched && (selectedValue == null || selectedValue === '') : false}
onFocus={() => setIsTouched(true)}
isInvalid={!isValid}
onFocus={setIsTouchedValue}
singleSelection={{ asPlainText: true }}
sortMatchesBy="startsWith"
data-test-subj="valuesAutocompleteComboBox listsComboxBox"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { uniq } from 'lodash';

import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete';
import { validateParams, getGenericComboBoxProps } from './helpers';
import { paramIsValid, getGenericComboBoxProps } from './helpers';
import { OperatorTypeEnum } from '../../../lists_plugin_deps';
import { GetGenericComboBoxPropsReturn } from './types';
import * as i18n from './translations';
Expand Down Expand Up @@ -82,25 +82,37 @@ export const AutocompleteFieldMatchComponent: React.FC<AutocompleteFieldMatchPro
});
};

const isValid = useMemo((): boolean => validateParams(selectedValue, selectedField), [
selectedField,
selectedValue,
const isValid = useMemo(
(): boolean => paramIsValid(selectedValue, selectedField, isRequired, touched),
[selectedField, selectedValue, isRequired, touched]
);

const setIsTouchedValue = useCallback((): void => setIsTouched(true), [setIsTouched]);

const inputPlaceholder = useMemo(
(): string => (isLoading || isLoadingSuggestions ? i18n.LOADING : placeholder),
[isLoading, isLoadingSuggestions, placeholder]
);

const isLoadingState = useMemo((): boolean => isLoading || isLoadingSuggestions, [
isLoading,
isLoadingSuggestions,
]);

return (
<EuiComboBox
placeholder={isLoading || isLoadingSuggestions ? i18n.LOADING : placeholder}
placeholder={inputPlaceholder}
isDisabled={isDisabled}
isLoading={isLoading || isLoadingSuggestions}
isLoading={isLoadingState}
isClearable={isClearable}
options={comboOptions}
selectedOptions={selectedComboOptions}
onChange={handleValuesChange}
singleSelection={{ asPlainText: true }}
onSearchChange={onSearchChange}
onCreateOption={onChange}
isInvalid={isRequired ? touched && !isValid : false}
onFocus={() => setIsTouched(true)}
isInvalid={!isValid}
onFocus={setIsTouchedValue}
sortMatchesBy="startsWith"
data-test-subj="valuesAutocompleteComboBox matchComboxBox"
style={fieldInputWidth ? { width: `${fieldInputWidth}px` } : {}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { uniq } from 'lodash';

import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete';
import { getGenericComboBoxProps, validateParams } from './helpers';
import { getGenericComboBoxProps, paramIsValid } from './helpers';
import { OperatorTypeEnum } from '../../../lists_plugin_deps';
import { GetGenericComboBoxPropsReturn } from './types';
import * as i18n from './translations';
Expand Down Expand Up @@ -78,25 +78,38 @@ export const AutocompleteFieldMatchAnyComponent: React.FC<AutocompleteFieldMatch
const onCreateOption = (option: string) => onChange([...(selectedValue || []), option]);

const isValid = useMemo((): boolean => {
const areAnyInvalid = selectedComboOptions.filter(
({ label }) => !validateParams(label, selectedField)
);
return areAnyInvalid.length === 0;
}, [selectedComboOptions, selectedField]);
const areAnyInvalid =
selectedComboOptions.filter(
({ label }) => !paramIsValid(label, selectedField, isRequired, touched)
).length > 0;
return !areAnyInvalid;
}, [selectedComboOptions, selectedField, isRequired, touched]);

const setIsTouchedValue = useCallback((): void => setIsTouched(true), [setIsTouched]);

const inputPlaceholder = useMemo(
(): string => (isLoading || isLoadingSuggestions ? i18n.LOADING : placeholder),
[isLoading, isLoadingSuggestions, placeholder]
);

const isLoadingState = useMemo((): boolean => isLoading || isLoadingSuggestions, [
isLoading,
isLoadingSuggestions,
]);

return (
<EuiComboBox
placeholder={isLoading || isLoadingSuggestions ? i18n.LOADING : placeholder}
isLoading={isLoading || isLoadingSuggestions}
placeholder={inputPlaceholder}
isLoading={isLoadingState}
isClearable={isClearable}
isDisabled={isDisabled}
options={comboOptions}
selectedOptions={selectedComboOptions}
onChange={handleValuesChange}
onSearchChange={onSearchChange}
onCreateOption={onCreateOption}
isInvalid={isRequired ? touched && (selectedValue.length === 0 || !isValid) : !isValid}
onFocus={() => setIsTouched(true)}
isInvalid={!isValid}
onFocus={setIsTouchedValue}
delimiter=", "
data-test-subj="valuesAutocompleteComboBox matchAnyComboxBox"
fullWidth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
existsOperator,
doesNotExistOperator,
} from './operators';
import { getOperators, validateParams, getGenericComboBoxProps } from './helpers';
import { getOperators, paramIsValid, getGenericComboBoxProps } from './helpers';

describe('helpers', () => {
describe('#getOperators', () => {
Expand Down Expand Up @@ -53,27 +53,67 @@ describe('helpers', () => {
});
});

describe('#validateParams', () => {
test('returns false if value is undefined', () => {
const isValid = validateParams(undefined, getField('@timestamp'));
describe('#paramIsValid', () => {
test('returns false if value is undefined and "isRequired" nad "touched" are true', () => {
const isValid = paramIsValid(undefined, getField('@timestamp'), true, true);

expect(isValid).toBeFalsy();
});

test('returns false if value is empty string', () => {
const isValid = validateParams('', getField('@timestamp'));
test('returns true if value is undefined and "isRequired" is true but "touched" is false', () => {
const isValid = paramIsValid(undefined, getField('@timestamp'), true, false);

expect(isValid).toBeFalsy();
expect(isValid).toBeTruthy();
});

test('returns true if value is undefined and "isRequired" is false', () => {
const isValid = paramIsValid(undefined, getField('@timestamp'), false, false);

expect(isValid).toBeTruthy();
});

test('returns false if value is empty string when "isRequired" is true and "touched" is false', () => {
const isValid = paramIsValid('', getField('@timestamp'), true, false);

expect(isValid).toBeTruthy();
});

test('returns true if value is empty string and "isRequired" is false', () => {
const isValid = paramIsValid('', getField('@timestamp'), false, false);

expect(isValid).toBeTruthy();
});

test('returns true if type is "date" and value is valid', () => {
const isValid = validateParams('1994-11-05T08:15:30-05:00', getField('@timestamp'));
test('returns true if type is "date" and value is valid and "isRequired" is false', () => {
const isValid = paramIsValid(
'1994-11-05T08:15:30-05:00',
getField('@timestamp'),
false,
false
);

expect(isValid).toBeTruthy();
});

test('returns false if type is "date" and value is not valid', () => {
const isValid = validateParams('1593478826', getField('@timestamp'));
test('returns true if type is "date" and value is valid and "isRequired" is true', () => {
const isValid = paramIsValid(
'1994-11-05T08:15:30-05:00',
getField('@timestamp'),
true,
false
);

expect(isValid).toBeTruthy();
});

test('returns false if type is "date" and value is not valid and "isRequired" is false', () => {
const isValid = paramIsValid('1593478826', getField('@timestamp'), false, false);

expect(isValid).toBeFalsy();
});

test('returns false if type is "date" and value is not valid and "isRequired" is true', () => {
const isValid = paramIsValid('1593478826', getField('@timestamp'), true, true);

expect(isValid).toBeFalsy();
});
Expand Down
Loading