Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] [Security Solution] `FinalEdit`: Add fields that are common for all rule types (#196642) #199743

Merged
merged 1 commit into from
Nov 12, 2024
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
2 changes: 1 addition & 1 deletion packages/kbn-securitysolution-autocomplete/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

export * from './src/check_empty_value';
export * from './src/field';
export * from './src/es_field_selector';
export * from './src/field_value_exists';
export * from './src/field_value_lists';
export * from './src/field_value_match';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import React from 'react';
import { fireEvent, render, waitFor, within } from '@testing-library/react';
import '@testing-library/jest-dom';

import { FieldComponent } from '..';
import { EsFieldSelector } 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
<EsFieldSelector
isClearable={false}
isDisabled={false}
isLoading={false}
Expand All @@ -38,7 +38,7 @@ describe('FieldComponent', () => {
});
it('should render the component disabled if isDisabled is true', () => {
const wrapper = render(
<FieldComponent
<EsFieldSelector
isClearable={false}
isDisabled={true}
isLoading={false}
Expand All @@ -57,7 +57,7 @@ describe('FieldComponent', () => {
});
it('should render the loading spinner if isLoading is true when clicked', () => {
const wrapper = render(
<FieldComponent
<EsFieldSelector
isClearable={false}
isDisabled={true}
isLoading={true}
Expand All @@ -78,7 +78,7 @@ describe('FieldComponent', () => {
});
it('should allow user to clear values if isClearable is true', () => {
const wrapper = render(
<FieldComponent
<EsFieldSelector
indexPattern={{
fields,
id: '1234',
Expand All @@ -97,7 +97,7 @@ describe('FieldComponent', () => {
});
it('should change the selected value', async () => {
const wrapper = render(
<FieldComponent
<EsFieldSelector
isClearable={false}
isDisabled={true}
isLoading={false}
Expand All @@ -119,7 +119,7 @@ describe('FieldComponent', () => {
it('it allows custom user input if "acceptsCustomOptions" is "true"', async () => {
const mockOnChange = jest.fn();
const wrapper = render(
<FieldComponent
<EsFieldSelector
indexPattern={{
fields,
id: '1234',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import TestRenderer from 'react-test-renderer';
const { act: actTestRenderer } = TestRenderer;

import { fields } from '../../fields/index.mock';
import { useField } from '../use_field';
import { useEsField } from '../use_es_field';

jest.mock('../../translations', () => ({
BINARY_TYPE_NOT_SUPPORTED: 'Binary fields are currently unsupported',
Expand All @@ -33,7 +33,7 @@ describe('useField', () => {

describe('comboOptions and selectedComboOptions', () => {
it('should return default values', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));
const { isInvalid, comboOptions, selectedComboOptions, fieldWidth } = result.current;
expect(isInvalid).toBeFalsy();
expect(comboOptions.length).toEqual(30);
Expand Down Expand Up @@ -79,7 +79,7 @@ describe('useField', () => {
};

const { result } = renderHook(() =>
useField({ indexPattern: newIndexPattern, onChange: onChangeMock })
useEsField({ indexPattern: newIndexPattern, onChange: onChangeMock })
);
const { comboOptions, selectedComboOptions } = result.current;
expect(comboOptions).toEqual([{ label: 'bytes' }, { label: 'ssl' }, { label: '@timestamp' }]);
Expand Down Expand Up @@ -124,7 +124,7 @@ describe('useField', () => {
};

const { result } = renderHook(() =>
useField({
useEsField({
indexPattern: newIndexPattern,
onChange: onChangeMock,
selectedField: { name: '', type: 'keyword' },
Expand Down Expand Up @@ -173,7 +173,7 @@ describe('useField', () => {
};

const { result } = renderHook(() =>
useField({
useEsField({
indexPattern: newIndexPattern,
onChange: onChangeMock,
selectedField: { name: ' ', type: 'keyword' },
Expand Down Expand Up @@ -222,7 +222,7 @@ describe('useField', () => {
};

const { result } = renderHook(() =>
useField({ indexPattern: newIndexPattern, onChange: onChangeMock, selectedField })
useEsField({ indexPattern: newIndexPattern, onChange: onChangeMock, selectedField })
);
const { comboOptions, selectedComboOptions } = result.current;
expect(comboOptions).toEqual([{ label: 'bytes' }, { label: 'ssl' }, { label: '@timestamp' }]);
Expand Down Expand Up @@ -273,7 +273,7 @@ describe('useField', () => {
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[];
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));
const { comboOptions, renderFields } = result.current;
expect(comboOptions).toEqual([
{ label: 'blob' },
Expand Down Expand Up @@ -328,7 +328,7 @@ describe('useField', () => {
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[];
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));
const { comboOptions, renderFields } = result.current;
expect(comboOptions).toEqual([
{ label: 'blob' },
Expand Down Expand Up @@ -374,7 +374,7 @@ describe('useField', () => {
readFromDocValues: true,
},
] as unknown as DataViewFieldBase[];
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));
const { comboOptions, renderFields } = result.current;
expect(comboOptions).toEqual([{ label: 'bytes' }, { label: 'ssl' }, { label: '@timestamp' }]);
act(() => {
Expand All @@ -389,7 +389,7 @@ describe('useField', () => {
jest.resetModules();
});
it('should invoke onChange with one value if one option is sent', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));
act(() => {
result.current.handleValuesChange([
{
Expand All @@ -411,7 +411,7 @@ describe('useField', () => {
});
});
it('should invoke onChange with array value if more than an option', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));
act(() => {
result.current.handleValuesChange([
{
Expand Down Expand Up @@ -446,7 +446,7 @@ describe('useField', () => {
});
});
it('should invoke onChange with custom option if one is sent', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));
act(() => {
result.current.handleCreateCustomOption('madeUpField');
expect(onChangeMock).toHaveBeenCalledWith([
Expand All @@ -462,13 +462,13 @@ describe('useField', () => {
describe('fieldWidth', () => {
it('should return object has width prop', () => {
const { result } = renderHook(() =>
useField({ indexPattern, onChange: onChangeMock, fieldInputWidth: 100 })
useEsField({ 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 })
useEsField({ indexPattern, onChange: onChangeMock, fieldInputWidth: 0 })
);
expect(result.current.fieldWidth).toEqual({});
});
Expand All @@ -477,7 +477,7 @@ describe('useField', () => {
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 })
useEsField({ indexPattern, onChange: onChangeMock, isRequired: true })
);

actTestRenderer(() => {
Expand All @@ -487,7 +487,7 @@ describe('useField', () => {
});
it('should return isInvalid equals false with selectedField and isRequired is true', () => {
const { result } = renderHook(() =>
useField({ indexPattern, onChange: onChangeMock, isRequired: true, selectedField })
useEsField({ indexPattern, onChange: onChangeMock, isRequired: true, selectedField })
);

actTestRenderer(() => {
Expand All @@ -496,7 +496,7 @@ describe('useField', () => {
expect(result.current.isInvalid).toBeFalsy();
});
it('should return isInvalid equals false when isRequired is false', () => {
const { result } = renderHook(() => useField({ indexPattern, onChange: onChangeMock }));
const { result } = renderHook(() => useEsField({ indexPattern, onChange: onChangeMock }));

actTestRenderer(() => {
result.current.handleTouch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,22 @@ import React from 'react';
import { EuiComboBox } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { FieldProps } from './types';
import { useField } from './use_field';
import { FieldBaseProps } from './types';
import { useEsField } from './use_es_field';

const AS_PLAIN_TEXT = { asPlainText: true };

export const FieldComponent: React.FC<FieldProps> = ({
interface EsFieldSelectorProps extends FieldBaseProps {
isClearable?: boolean;
isDisabled?: boolean;
isLoading?: boolean;
placeholder: string;
acceptsCustomOptions?: boolean;
showMappingConflicts?: boolean;
'aria-label'?: string;
}

export function EsFieldSelector({
fieldInputWidth,
fieldTypeFilter = [],
indexPattern,
Expand All @@ -30,18 +40,17 @@ export const FieldComponent: React.FC<FieldProps> = ({
acceptsCustomOptions = false,
showMappingConflicts = false,
'aria-label': ariaLabel,
}): JSX.Element => {
}: EsFieldSelectorProps): JSX.Element {
const {
isInvalid,
comboOptions,
selectedComboOptions,
fieldWidth,

renderFields,
handleTouch,
handleValuesChange,
handleCreateCustomOption,
} = useField({
} = useEsField({
indexPattern,
fieldTypeFilter,
isRequired,
Expand Down Expand Up @@ -97,6 +106,4 @@ export const FieldComponent: React.FC<FieldProps> = ({
aria-label={ariaLabel}
/>
);
};

FieldComponent.displayName = 'Field';
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ import { DataViewBase, DataViewFieldBase } from '@kbn/es-query';
import { FieldConflictsInfo } from '@kbn/securitysolution-list-utils';
import { GetGenericComboBoxPropsReturn } from '../get_generic_combo_box_props';

export interface FieldProps extends FieldBaseProps {
isClearable: boolean;
isDisabled: boolean;
isLoading: boolean;
placeholder: string;
acceptsCustomOptions?: boolean;
showMappingConflicts?: boolean;
'aria-label'?: string;
}
export interface FieldBaseProps {
indexPattern: DataViewBase | undefined;
fieldTypeFilter?: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const getComboBoxProps = (fields: ComboBoxFields): GetFieldComboBoxPropsReturn =
};
};

export const useField = ({
export const useEsField = ({
indexPattern,
fieldTypeFilter,
isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ interface AutocompleteFieldMatchProps {
selectedField: DataViewFieldBase | undefined;
selectedValue: string | undefined;
indexPattern: DataViewBase | undefined;
isLoading: boolean;
isDisabled: boolean;
isClearable: boolean;
isLoading?: boolean;
isDisabled?: boolean;
isClearable?: boolean;
isRequired?: boolean;
fieldInputWidth?: number;
rowLabel?: string;
Expand All @@ -68,7 +68,7 @@ export const AutocompleteFieldMatchComponent: React.FC<AutocompleteFieldMatchPro
selectedField,
selectedValue,
indexPattern,
isLoading,
isLoading = false,
isDisabled = false,
isClearable = false,
isRequired = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
AutocompleteFieldMatchAnyComponent,
AutocompleteFieldMatchComponent,
AutocompleteFieldWildcardComponent,
FieldComponent,
EsFieldSelector,
OperatorComponent,
} from '@kbn/securitysolution-autocomplete';
import {
Expand Down Expand Up @@ -207,7 +207,7 @@ export const BuilderEntryItem: React.FC<EntryItemProps> = ({
(isFirst: boolean): JSX.Element => {
const filteredIndexPatterns = getFilteredIndexPatterns(indexPattern, entry);
const comboBox = (
<FieldComponent
<EsFieldSelector
placeholder={
entry.nested != null
? i18n.EXCEPTION_FIELD_NESTED_PLACEHOLDER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import React, { useCallback, useMemo } from 'react';
import { EuiFormRow, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import styled from 'styled-components';

import { FieldComponent } from '@kbn/securitysolution-autocomplete';
import { EsFieldSelector } from '@kbn/securitysolution-autocomplete';
import type { DataViewBase, DataViewFieldBase } from '@kbn/es-query';
import type { FormattedEntry, Entry } from './types';
import * as i18n from './translations';
Expand Down Expand Up @@ -57,7 +57,7 @@ export const EntryItem: React.FC<EntryItemProps> = ({

const renderFieldInput = useMemo(() => {
const comboBox = (
<FieldComponent
<EsFieldSelector
placeholder={i18n.FIELD_PLACEHOLDER}
indexPattern={indexPattern}
selectedField={entry.field}
Expand Down Expand Up @@ -87,7 +87,7 @@ export const EntryItem: React.FC<EntryItemProps> = ({

const renderThreatFieldInput = useMemo(() => {
const comboBox = (
<FieldComponent
<EsFieldSelector
placeholder={i18n.FIELD_PLACEHOLDER}
indexPattern={threatIndexPatterns}
selectedField={entry.value}
Expand Down
Loading