Disable Binary field type in Exception entries (#139370)

* refactor field.tsx+ introduce useField and types

* handle binary disabled field

* finish hooks tests + disabled types test

* apply docs-team comments

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Wafaa Nasr 2022-09-19 20:48:09 +02:00 committed by GitHub
parent 8089c01a13
commit ef2f33f873
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 1477 additions and 184 deletions

View file

@ -0,0 +1,765 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FieldComponent should allow user to clear values if isClearable is true 1`] = `
Object {
"asFragment": [Function],
"baseElement": <body>
<div>
<div
class="euiComboBox euiComboBox--fullWidth"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap euiComboBox__inputWrap-isClearable"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<button
aria-label="Clear input"
class="euiFormControlLayoutClearButton"
data-test-subj="comboBoxClearButton"
type="button"
>
<span
class="euiFormControlLayoutClearButton__icon"
data-euiicon-type="cross"
/>
</button>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>
</body>,
"container": <div>
<div
class="euiComboBox euiComboBox--fullWidth"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap euiComboBox__inputWrap-isClearable"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<button
aria-label="Clear input"
class="euiFormControlLayoutClearButton"
data-test-subj="comboBoxClearButton"
type="button"
>
<span
class="euiFormControlLayoutClearButton__icon"
data-euiicon-type="cross"
/>
</button>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
exports[`FieldComponent should render the component disabled if isDisabled is true 1`] = `
Object {
"asFragment": [Function],
"baseElement": <body>
<div>
<div
class="euiComboBox euiComboBox--fullWidth euiComboBox-isDisabled"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
disabled=""
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
disabled=""
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>
</body>,
"container": <div>
<div
class="euiComboBox euiComboBox--fullWidth euiComboBox-isDisabled"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
disabled=""
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
disabled=""
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
exports[`FieldComponent should render the component enabled and displays the selected field correctly 1`] = `
Object {
"asFragment": [Function],
"baseElement": <body>
<div>
<div
class="euiComboBox euiComboBox--fullWidth"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>
</body>,
"container": <div>
<div
class="euiComboBox euiComboBox--fullWidth"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
exports[`FieldComponent should render the loading spinner if isLoading is true when clicked 1`] = `
Object {
"asFragment": [Function],
"baseElement": <body>
<div>
<div
class="euiComboBox euiComboBox--fullWidth euiComboBox-isDisabled"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap euiComboBox__inputWrap-isLoading"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
disabled=""
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<span
aria-label="Loading"
class="euiLoadingSpinner emotion-euiLoadingSpinner-m"
role="progressbar"
/>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
disabled=""
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>
</body>,
"container": <div>
<div
class="euiComboBox euiComboBox--fullWidth euiComboBox-isDisabled"
data-test-subj="fieldAutocompleteComboBox"
>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiComboBox__inputWrap euiComboBox__inputWrap--fullWidth euiComboBox__inputWrap--noWrap euiComboBox__inputWrap-isLoading"
data-test-subj="comboBoxInput"
tabindex="-1"
>
<span
class="euiComboBoxPill euiComboBoxPill--plainText"
>
machine.os.raw
</span>
<div
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
data-test-subj="comboBoxSearchInput"
disabled=""
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<span
aria-label="Loading"
class="euiLoadingSpinner emotion-euiLoadingSpinner-m"
role="progressbar"
/>
<button
aria-label="Open list of options"
class="euiFormControlLayoutCustomIcon euiFormControlLayoutCustomIcon--clickable"
data-test-subj="comboBoxToggleListButton"
disabled=""
tabindex="-1"
type="button"
>
<span
aria-hidden="true"
class="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</button>
</div>
</div>
</div>
</div>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;

View file

@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { disabledTypesWithTooltipText } from '../disabled_types_with_tooltip_text';
jest.mock('../../translations', () => ({
BINARY_TYPE_NOT_SUPPORTED: 'Binary fields are currently unsupported',
}));
describe('disabledTypesWithTooltipText', () => {
it('should return Binary fields are currently unsupported for binary type', () => {
const type = 'binary';
expect(disabledTypesWithTooltipText[type]).toEqual('Binary fields are currently unsupported');
});
});

View file

@ -7,14 +7,34 @@
*/
import React from 'react';
import { mount } from 'enzyme';
import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
import { FieldComponent } from '.';
import { fields, getField } from '../fields/index.mock';
import { fireEvent, render, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
describe('field', () => {
test('it renders disabled if "isDisabled" is true', () => {
const wrapper = mount(
import { FieldComponent } from '..';
import { fields, getField } from '../../fields/index.mock';
describe('FieldComponent', () => {
it('should render the component enabled and displays the selected field correctly', () => {
const wrapper = render(
<FieldComponent
isClearable={false}
isDisabled={false}
isLoading={false}
indexPattern={{
fields,
id: '1234',
title: 'logstash-*',
}}
onChange={jest.fn()}
placeholder="Placeholder text"
selectedField={getField('machine.os.raw')}
/>
);
expect(wrapper).toMatchSnapshot();
expect(wrapper.getByTestId('fieldAutocompleteComboBox')).toHaveTextContent('machine.os.raw');
});
it('should render the component disabled if isDisabled is true', () => {
const wrapper = render(
<FieldComponent
isClearable={false}
isDisabled={true}
@ -29,38 +49,32 @@ describe('field', () => {
selectedField={getField('machine.os.raw')}
/>
);
expect(
wrapper.find(`[data-test-subj="fieldAutocompleteComboBox"] input`).prop('disabled')
).toBeTruthy();
expect(wrapper).toMatchSnapshot();
expect(wrapper.getByTestId('fieldAutocompleteComboBox').querySelector('input')).toBeDisabled();
});
test('it renders loading if "isLoading" is true', () => {
const wrapper = mount(
it('should render the loading spinner if isLoading is true when clicked', () => {
const wrapper = render(
<FieldComponent
isClearable={false}
isDisabled={true}
isLoading={true}
indexPattern={{
fields,
id: '1234',
title: 'logstash-*',
}}
isClearable={false}
isDisabled={false}
isLoading={true}
onChange={jest.fn()}
placeholder="Placeholder text"
selectedField={getField('machine.os.raw')}
/>
);
wrapper.find(`[data-test-subj="fieldAutocompleteComboBox"] button`).at(0).simulate('click');
expect(
wrapper
.find(`EuiComboBoxOptionsList[data-test-subj="fieldAutocompleteComboBox-optionsList"]`)
.prop('isLoading')
).toBeTruthy();
const fieldAutocompleteComboBox = wrapper.getByTestId('fieldAutocompleteComboBox');
expect(wrapper).toMatchSnapshot();
fireEvent.click(fieldAutocompleteComboBox);
expect(wrapper.getByRole('progressbar')).toBeInTheDocument();
});
test('it allows user to clear values if "isClearable" is true', () => {
const wrapper = mount(
it('should allow user to clear values if isClearable is true', () => {
const wrapper = render(
<FieldComponent
indexPattern={{
fields,
@ -75,71 +89,29 @@ describe('field', () => {
selectedField={getField('machine.os.raw')}
/>
);
expect(
wrapper
.find(`[data-test-subj="comboBoxInput"]`)
.hasClass('euiComboBox__inputWrap-isClearable')
).toBeTruthy();
expect(wrapper).toMatchSnapshot();
expect(wrapper.getByTestId('comboBoxClearButton')).toBeInTheDocument();
});
test('it correctly displays selected field', () => {
const wrapper = mount(
it('should change the selected value', async () => {
const wrapper = render(
<FieldComponent
isClearable={false}
isDisabled={true}
isLoading={false}
indexPattern={{
fields,
id: '1234',
title: 'logstash-*',
}}
isClearable={false}
isDisabled={false}
isLoading={false}
onChange={jest.fn()}
placeholder="Placeholder text"
selectedField={getField('machine.os.raw')}
/>
);
expect(
wrapper.find(`[data-test-subj="fieldAutocompleteComboBox"] EuiComboBoxPill`).at(0).text()
).toEqual('machine.os.raw');
});
test('it invokes "onChange" when option selected', () => {
const mockOnChange = jest.fn();
const wrapper = mount(
<FieldComponent
indexPattern={{
fields,
id: '1234',
title: 'logstash-*',
}}
isClearable={false}
isDisabled={false}
isLoading={false}
onChange={mockOnChange}
placeholder="Placeholder text"
selectedField={getField('machine.os.raw')}
/>
const fieldAutocompleteComboBox = wrapper.getByTestId('comboBoxSearchInput');
fireEvent.change(fieldAutocompleteComboBox, { target: { value: '_source' } });
await waitFor(() =>
expect(wrapper.getByTestId('fieldAutocompleteComboBox')).toHaveTextContent('_source')
);
(
wrapper.find(EuiComboBox).props() as unknown as {
onChange: (a: EuiComboBoxOptionOption[]) => void;
}
).onChange([{ label: 'machine.os' }]);
expect(mockOnChange).toHaveBeenCalledWith([
{
aggregatable: true,
count: 0,
esTypes: ['text'],
name: 'machine.os',
readFromDocValues: false,
scripted: false,
searchable: true,
type: 'string',
},
]);
});
});

View file

@ -0,0 +1,396 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { DataViewFieldBase } from '@kbn/es-query';
import { ReactElement } from 'react';
import { act } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';
import TestRenderer from 'react-test-renderer';
const { act: actTestRenderer } = TestRenderer;
import { fields } from '../../fields/index.mock';
import { useField } from '../use_field';
jest.mock('../../translations', () => ({
BINARY_TYPE_NOT_SUPPORTED: 'Binary fields are currently unsupported',
}));
const indexPattern = { fields, title: 'title' };
const onChangeMock = jest.fn();
const selectedField = { name: '@timestamp', type: 'date' };
describe('useField', () => {
beforeEach(() => {
jest.resetAllMocks();
jest.resetModules();
});
describe('comboOptions and selectedComboOptions', () => {
it('should return default values', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { isInvalid, comboOptions, selectedComboOptions, fieldWidth } = result.current;
expect(isInvalid).toBeFalsy();
expect(comboOptions.length).toEqual(30);
expect(selectedComboOptions.length).toEqual(0);
expect(fieldWidth).toEqual({});
});
it('should map fields to comboOptions correctly and return empty selectedComboOptions', () => {
const newIndexPattern = {
...indexPattern,
fields: [
{
name: 'bytes',
type: 'number',
esTypes: ['long'],
count: 10,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: 'ssl',
type: 'boolean',
esTypes: ['boolean'],
count: 20,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: '@timestamp',
type: 'date',
esTypes: ['date'],
count: 30,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[],
title: 'title1',
};
const { result } = renderHook(() =>
useField({ indexPattern: newIndexPattern, onChange: onChangeMock })
);
const { comboOptions, selectedComboOptions } = result.current;
expect(comboOptions).toEqual([{ label: 'bytes' }, { label: 'ssl' }, { label: '@timestamp' }]);
expect(selectedComboOptions).toEqual([]);
});
it('should map fields to comboOptions correctly and return selectedComboOptions', () => {
const newIndexPattern = {
...indexPattern,
fields: [
{
name: 'bytes',
type: 'number',
esTypes: ['long'],
count: 10,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: 'ssl',
type: 'boolean',
esTypes: ['boolean'],
count: 20,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: '@timestamp',
type: 'date',
esTypes: ['date'],
count: 30,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[],
title: 'title1',
};
const { result } = renderHook(() =>
useField({ indexPattern: newIndexPattern, onChange: onChangeMock, selectedField })
);
const { comboOptions, selectedComboOptions } = result.current;
expect(comboOptions).toEqual([{ label: 'bytes' }, { label: 'ssl' }, { label: '@timestamp' }]);
expect(selectedComboOptions).toEqual([{ label: '@timestamp' }]);
});
});
describe('getDisabledLabelTooltipTexts and renderFields', () => {
it('should return label as component and disable the binary field type if field.esType has one the disabled types', () => {
indexPattern.fields = [
{
name: 'blob',
type: 'unknown',
esTypes: ['binary'],
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: 'bytes',
type: 'number',
esTypes: ['long'],
count: 10,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: 'ssl',
type: 'boolean',
esTypes: ['boolean'],
count: 20,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: '@timestamp',
type: 'date',
esTypes: ['date'],
count: 30,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[];
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { comboOptions, renderFields } = result.current;
expect(comboOptions).toEqual([
{ label: 'blob' },
{ label: 'bytes' },
{ label: 'ssl' },
{ label: '@timestamp' },
]);
act(() => {
const label = renderFields({ label: 'blob' }, '', '') as ReactElement;
expect(label?.props.content).toEqual('Binary fields are currently unsupported');
});
});
it('should return label as component and disable the binary field type if field.type is one of the disabled types', () => {
indexPattern.fields = [
{
name: 'blob',
type: 'binary',
esTypes: [],
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: 'bytes',
type: 'number',
esTypes: ['long'],
count: 10,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: 'ssl',
type: 'boolean',
esTypes: ['boolean'],
count: 20,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: '@timestamp',
type: 'date',
esTypes: ['date'],
count: 30,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[];
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { comboOptions, renderFields } = result.current;
expect(comboOptions).toEqual([
{ label: 'blob' },
{ label: 'bytes' },
{ label: 'ssl' },
{ label: '@timestamp' },
]);
act(() => {
const label = renderFields({ label: 'blob' }, '', '') as ReactElement;
expect(label?.props.content).toEqual('Binary fields are currently unsupported');
});
});
it('should return label as string', () => {
indexPattern.fields = [
{
name: 'bytes',
type: 'number',
esTypes: ['long'],
count: 10,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: 'ssl',
type: 'boolean',
esTypes: ['boolean'],
count: 20,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
{
name: '@timestamp',
type: 'date',
esTypes: ['date'],
count: 30,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[];
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { comboOptions, renderFields } = result.current;
expect(comboOptions).toEqual([{ label: 'bytes' }, { label: 'ssl' }, { label: '@timestamp' }]);
act(() => {
const label = renderFields({ label: '@timestamp' }, '', '') as ReactElement;
expect(label).toEqual('@timestamp');
});
});
});
describe('handleValuesChange', () => {
beforeEach(() => {
jest.resetAllMocks();
jest.resetModules();
});
it('should invoke onChange with one value if one option is sent', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
act(() => {
result.current.handleValuesChange([
{
label: '@timestamp',
},
]);
expect(onChangeMock).toHaveBeenCalledWith([
{
aggregatable: true,
count: 30,
esTypes: ['date'],
name: '@timestamp',
readFromDocValues: true,
scripted: false,
searchable: true,
type: 'date',
},
]);
});
});
it('should invoke onChange with array value if more than an option', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
act(() => {
result.current.handleValuesChange([
{
label: '@timestamp',
},
{
label: 'ssl',
},
]);
expect(onChangeMock).toHaveBeenCalledWith([
{
aggregatable: true,
count: 30,
esTypes: ['date'],
name: '@timestamp',
readFromDocValues: true,
scripted: false,
searchable: true,
type: 'date',
},
{
name: 'ssl',
type: 'boolean',
esTypes: ['boolean'],
count: 20,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
]);
});
});
});
describe('fieldWidth', () => {
it('should return object has width prop', () => {
const { result } = renderHook(() =>
useField({ indexPattern, onChange: onChangeMock, fieldInputWidth: 100 })
);
expect(result.current.fieldWidth).toEqual({ width: '100px' });
});
it('should return empty object', () => {
const { result } = renderHook(() =>
useField({ indexPattern, onChange: onChangeMock, fieldInputWidth: 0 })
);
expect(result.current.fieldWidth).toEqual({});
});
});
describe('isInvalid with handleTouch', () => {
it('should return isInvalid equals true when calling with no selectedField and isRequired is true', () => {
const { result } = renderHook(() =>
useField({ indexPattern, onChange: onChangeMock, isRequired: true })
);
actTestRenderer(() => {
result.current.handleTouch();
});
expect(result.current.isInvalid).toBeTruthy();
});
it('should return isInvalid equals false with selectedField and isRequired is true', () => {
const { result } = renderHook(() =>
useField({ indexPattern, onChange: onChangeMock, isRequired: true, selectedField })
);
actTestRenderer(() => {
result.current.handleTouch();
});
expect(result.current.isInvalid).toBeFalsy();
});
it('should return isInvalid equals false when isRequired is false', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
actTestRenderer(() => {
result.current.handleTouch();
});
expect(result.current.isInvalid).toBeFalsy();
});
});
});

View file

@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
interface DisabledTypesTextType {
[typeName: string]: string;
}
import * as i18n from '../translations';
export const disabledTypesWithTooltipText: DisabledTypesTextType = {
binary: i18n.BINARY_TYPE_NOT_SUPPORTED,
};

View file

@ -6,31 +6,15 @@
* Side Public License, v 1.
*/
import React, { useCallback, useMemo, useState } from 'react';
import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
import { DataViewBase, DataViewFieldBase } from '@kbn/es-query';
import React from 'react';
import { EuiComboBox } from '@elastic/eui';
import {
getGenericComboBoxProps,
GetGenericComboBoxPropsReturn,
} from '../get_generic_combo_box_props';
import { FieldProps } from './types';
import { useField } from './use_field';
const AS_PLAIN_TEXT = { asPlainText: true };
interface OperatorProps {
fieldInputWidth?: number;
fieldTypeFilter?: string[];
indexPattern: DataViewBase | undefined;
isClearable: boolean;
isDisabled: boolean;
isLoading: boolean;
isRequired?: boolean;
onChange: (a: DataViewFieldBase[]) => void;
placeholder: string;
selectedField: DataViewFieldBase | undefined;
}
export const FieldComponent: React.FC<OperatorProps> = ({
export const FieldComponent: React.FC<FieldProps> = ({
fieldInputWidth,
fieldTypeFilter = [],
indexPattern,
@ -42,36 +26,23 @@ export const FieldComponent: React.FC<OperatorProps> = ({
placeholder,
selectedField,
}): JSX.Element => {
const [touched, setIsTouched] = useState(false);
const { availableFields, selectedFields } = useMemo(
() => getComboBoxFields(indexPattern, selectedField, fieldTypeFilter),
[indexPattern, selectedField, fieldTypeFilter]
);
const { comboOptions, labels, selectedComboOptions } = useMemo(
() => getComboBoxProps({ availableFields, selectedFields }),
[availableFields, selectedFields]
);
const handleValuesChange = useCallback(
(newOptions: EuiComboBoxOptionOption[]): void => {
const newValues: DataViewFieldBase[] = newOptions.map(
({ label }) => availableFields[labels.indexOf(label)]
);
onChange(newValues);
},
[availableFields, labels, onChange]
);
const handleTouch = useCallback((): void => {
setIsTouched(true);
}, [setIsTouched]);
const fieldWidth = useMemo(() => {
return fieldInputWidth ? { width: `${fieldInputWidth}px` } : {};
}, [fieldInputWidth]);
const {
isInvalid,
comboOptions,
selectedComboOptions,
fieldWidth,
renderFields,
handleTouch,
handleValuesChange,
} = useField({
indexPattern,
fieldTypeFilter,
isRequired,
selectedField,
fieldInputWidth,
onChange,
});
return (
<EuiComboBox
placeholder={placeholder}
@ -81,68 +52,15 @@ export const FieldComponent: React.FC<OperatorProps> = ({
isLoading={isLoading}
isDisabled={isDisabled}
isClearable={isClearable}
isInvalid={isRequired ? touched && selectedField == null : false}
isInvalid={isInvalid}
onFocus={handleTouch}
singleSelection={AS_PLAIN_TEXT}
data-test-subj="fieldAutocompleteComboBox"
style={fieldWidth}
fullWidth
renderOption={renderFields}
/>
);
};
FieldComponent.displayName = 'Field';
interface ComboBoxFields {
availableFields: DataViewFieldBase[];
selectedFields: DataViewFieldBase[];
}
const getComboBoxFields = (
indexPattern: DataViewBase | undefined,
selectedField: DataViewFieldBase | undefined,
fieldTypeFilter: string[]
): ComboBoxFields => {
const existingFields = getExistingFields(indexPattern);
const selectedFields = getSelectedFields(selectedField);
const availableFields = getAvailableFields(existingFields, selectedFields, fieldTypeFilter);
return { availableFields, selectedFields };
};
const getComboBoxProps = (fields: ComboBoxFields): GetGenericComboBoxPropsReturn => {
const { availableFields, selectedFields } = fields;
return getGenericComboBoxProps<DataViewFieldBase>({
getLabel: (field) => field.name,
options: availableFields,
selectedOptions: selectedFields,
});
};
const getExistingFields = (indexPattern: DataViewBase | undefined): DataViewFieldBase[] => {
return indexPattern != null ? indexPattern.fields : [];
};
const getSelectedFields = (selectedField: DataViewFieldBase | undefined): DataViewFieldBase[] => {
return selectedField ? [selectedField] : [];
};
const getAvailableFields = (
existingFields: DataViewFieldBase[],
selectedFields: DataViewFieldBase[],
fieldTypeFilter: string[]
): DataViewFieldBase[] => {
const fieldsByName = new Map<string, DataViewFieldBase>();
existingFields.forEach((f) => fieldsByName.set(f.name, f));
selectedFields.forEach((f) => fieldsByName.set(f.name, f));
const uniqueFields = Array.from(fieldsByName.values());
if (fieldTypeFilter.length > 0) {
return uniqueFields.filter(({ type }) => fieldTypeFilter.includes(type));
}
return uniqueFields;
};

View file

@ -0,0 +1,38 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { DataViewBase, DataViewFieldBase } from '@kbn/es-query';
import { GetGenericComboBoxPropsReturn } from '../get_generic_combo_box_props';
export interface FieldProps extends FieldBaseProps {
isClearable: boolean;
isDisabled: boolean;
isLoading: boolean;
placeholder: string;
}
export interface FieldBaseProps {
indexPattern: DataViewBase | undefined;
fieldTypeFilter?: string[];
isRequired?: boolean;
selectedField?: DataViewFieldBase | undefined;
fieldInputWidth?: number;
onChange: (a: DataViewFieldBase[]) => void;
}
export interface ComboBoxFields {
availableFields: DataViewField[];
selectedFields: DataViewField[];
}
export interface GetFieldComboBoxPropsReturn extends GetGenericComboBoxPropsReturn {
disabledLabelTooltipTexts: { [label: string]: string };
}
export interface DataViewField extends DataViewFieldBase {
esTypes?: string[];
}

View file

@ -0,0 +1,165 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { useCallback, useMemo, useState } from 'react';
import { EuiComboBoxOptionOption, EuiToolTip } from '@elastic/eui';
import { DataViewBase, DataViewFieldBase } from '@kbn/es-query';
import { getGenericComboBoxProps } from '../get_generic_combo_box_props';
import {
ComboBoxFields,
DataViewField,
FieldBaseProps,
GetFieldComboBoxPropsReturn,
} from './types';
import { disabledTypesWithTooltipText } from './disabled_types_with_tooltip_text';
const getExistingFields = (indexPattern: DataViewBase | undefined): DataViewFieldBase[] => {
return indexPattern != null ? indexPattern.fields : [];
};
const getSelectedFields = (selectedField: DataViewField | undefined): DataViewFieldBase[] => {
return selectedField ? [selectedField] : [];
};
const getAvailableFields = (
existingFields: DataViewField[],
selectedFields: DataViewField[],
fieldTypeFilter: string[] | undefined
): DataViewField[] => {
const fieldsByName = new Map<string, DataViewField>();
existingFields.forEach((f) => fieldsByName.set(f.name, f));
selectedFields.forEach((f) => fieldsByName.set(f.name, f));
const uniqueFields = Array.from(fieldsByName.values());
if (fieldTypeFilter && fieldTypeFilter?.length > 0) {
return uniqueFields.filter(({ type }) => fieldTypeFilter.includes(type));
}
return uniqueFields;
};
const getComboBoxFields = (
indexPattern: DataViewBase | undefined,
selectedField: DataViewField | undefined,
fieldTypeFilter: string[] | undefined
): ComboBoxFields => {
const existingFields = getExistingFields(indexPattern);
const selectedFields = getSelectedFields(selectedField);
const availableFields = getAvailableFields(existingFields, selectedFields, fieldTypeFilter);
return { availableFields, selectedFields };
};
const getDisabledLabelTooltipTexts = (fields: ComboBoxFields) => {
const disabledLabelTooltipTexts = fields.availableFields.reduce(
(acc: { [label: string]: string }, field: DataViewField) => {
const esTypeKey = field.esTypes?.find((type) => disabledTypesWithTooltipText[type]);
const tooltipText =
(esTypeKey && disabledTypesWithTooltipText[esTypeKey]) ||
disabledTypesWithTooltipText[field.type];
if (tooltipText) acc[field.name] = tooltipText;
return acc;
},
{}
);
return disabledLabelTooltipTexts;
};
const getComboBoxProps = (fields: ComboBoxFields): GetFieldComboBoxPropsReturn => {
const { availableFields, selectedFields } = fields;
const genericProps = getGenericComboBoxProps<DataViewFieldBase>({
getLabel: (field) => field.name,
options: availableFields,
selectedOptions: selectedFields,
});
const disabledLabelTooltipTexts = getDisabledLabelTooltipTexts(fields);
return {
...genericProps,
disabledLabelTooltipTexts,
};
};
export const useField = ({
indexPattern,
fieldTypeFilter,
isRequired,
selectedField,
fieldInputWidth,
onChange,
}: FieldBaseProps) => {
const [touched, setIsTouched] = useState(false);
const { availableFields, selectedFields } = useMemo(
() => getComboBoxFields(indexPattern, selectedField, fieldTypeFilter),
[indexPattern, fieldTypeFilter, selectedField]
);
const { comboOptions, labels, selectedComboOptions, disabledLabelTooltipTexts } = useMemo(
() => getComboBoxProps({ availableFields, selectedFields }),
[availableFields, selectedFields]
);
const handleValuesChange = useCallback(
(newOptions: EuiComboBoxOptionOption[]): void => {
const newValues: DataViewFieldBase[] = newOptions.map(
({ label }) => availableFields[labels.indexOf(label)]
);
onChange(newValues);
},
[availableFields, labels, onChange]
);
const handleTouch = useCallback((): void => {
setIsTouched(true);
}, [setIsTouched]);
const fieldWidth = useMemo(() => {
return fieldInputWidth ? { width: `${fieldInputWidth}px` } : {};
}, [fieldInputWidth]);
const isInvalid = useMemo(
() => (isRequired ? touched && selectedField == null : false),
[isRequired, selectedField, touched]
);
const renderFields = (
option: EuiComboBoxOptionOption<string | number | string[] | undefined>,
searchValue: string,
contentClassName: string
) => {
const { label } = option;
const labelTooltipText = disabledLabelTooltipTexts[label];
if (labelTooltipText) {
option.disabled = true;
return (
<EuiToolTip
data-test-subj="disabledLabelWithTooltip"
content={labelTooltipText}
position="bottom"
>
<>{label}</>
</EuiToolTip>
);
}
return label;
};
return {
isInvalid,
comboOptions,
selectedComboOptions,
fieldWidth,
renderFields,
handleTouch,
handleValuesChange,
};
};

View file

@ -28,6 +28,9 @@ export const DATE_ERR = i18n.translate('autocomplete.invalidDateError', {
defaultMessage: 'Not a valid date',
});
export const BINARY_TYPE_NOT_SUPPORTED = i18n.translate('autocomplete.invalidBinaryType', {
defaultMessage: 'Binary fields are currently unsupported',
});
export const FIELD_SPACE_WARNING = i18n.translate('autocomplete.fieldSpaceWarning', {
defaultMessage: "Warning: Spaces at the start or end of this value aren't being displayed.",
});
@ -40,4 +43,5 @@ export default {
NUMBER_ERR,
DATE_ERR,
FIELD_SPACE_WARNING,
BINARY_TYPE_NOT_SUPPORTED,
};