mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ResponseOps] Do not change time field when edit (#206858)
Fixed: https://github.com/elastic/kibana/issues/204432 How to test: Go to rules creation. Create ESquery rule. Set some `@timestamp` time field. Try to edit rule. Check if it's save previous value of time field. Check the PR satisfies following conditions. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
5c59f3bdcd
commit
993392bc4f
2 changed files with 102 additions and 30 deletions
|
@ -6,9 +6,8 @@
|
|||
*/
|
||||
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react';
|
||||
import { fireEvent, render, waitFor, screen, act } from '@testing-library/react';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
|
||||
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
|
||||
import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
|
||||
import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks';
|
||||
|
@ -24,6 +23,40 @@ const { hasExpressionValidationErrors } = jest.requireMock('../validation');
|
|||
jest.mock('@kbn/esql-editor', () => ({
|
||||
fetchFieldsFromESQL: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@kbn/triggers-actions-ui-plugin/public', () => {
|
||||
const module = jest.requireActual('@kbn/kibana-react-plugin/public');
|
||||
return {
|
||||
...module,
|
||||
getFields: jest.fn().mockResolvedValue([]),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@kbn/triggers-actions-ui-plugin/public/common', () => {
|
||||
const module = jest.requireActual('@kbn/triggers-actions-ui-plugin/public/common');
|
||||
return {
|
||||
...module,
|
||||
getTimeOptions: jest.fn(),
|
||||
firstFieldOption: { text: '@timestamp', value: '@timestamp' },
|
||||
getTimeFieldOptions: jest.fn().mockReturnValue([
|
||||
{ value: '@timestamp', text: '@timestamp' },
|
||||
{ value: 'event.ingested', text: 'event.ingested' },
|
||||
]),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@kbn/esql-utils', () => {
|
||||
return {
|
||||
getESQLResults: jest.fn().mockResolvedValue({}),
|
||||
getIndexPattern: jest.fn(),
|
||||
getIndexPatternFromESQLQuery: jest.fn().mockReturnValue('index1'),
|
||||
getESQLAdHocDataview: jest
|
||||
.fn()
|
||||
.mockResolvedValue({ timeFieldName: '@timestamp', getIndexPattern: jest.fn() }),
|
||||
formatESQLColumns: jest.fn().mockReturnValue([]),
|
||||
};
|
||||
});
|
||||
|
||||
const { fetchFieldsFromESQL } = jest.requireMock('@kbn/esql-editor');
|
||||
const { getFields } = jest.requireMock('@kbn/triggers-actions-ui-plugin/public');
|
||||
|
||||
|
@ -58,6 +91,39 @@ describe('EsqlQueryRuleTypeExpression', () => {
|
|||
hasExpressionValidationErrors.mockReturnValue(false);
|
||||
});
|
||||
|
||||
test('should render EsqlQueryRuleTypeExpression with chosen time field', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<EsqlQueryExpression
|
||||
unifiedSearch={unifiedSearchMock}
|
||||
ruleInterval="1m"
|
||||
ruleThrottle="1m"
|
||||
alertNotifyWhen="onThrottleInterval"
|
||||
ruleParams={{
|
||||
...defaultEsqlQueryExpressionParams,
|
||||
timeField: 'event.ingested',
|
||||
esqlQuery: { esql: 'FROM *' },
|
||||
}}
|
||||
setRuleParams={() => {}}
|
||||
setRuleProperty={() => {}}
|
||||
errors={{ esqlQuery: [], timeField: [], timeWindowSize: [] }}
|
||||
data={dataMock}
|
||||
dataViews={dataViewMock}
|
||||
defaultActionGroupId=""
|
||||
actionGroups={[]}
|
||||
charts={chartsStartMock}
|
||||
onChangeMetaData={() => {}}
|
||||
/>,
|
||||
{
|
||||
wrapper: AppWrapper,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const timeFieldText = await screen.findByText('event.ingested');
|
||||
expect(timeFieldText).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render EsqlQueryRuleTypeExpression with expected components', () => {
|
||||
const result = render(
|
||||
<EsqlQueryExpression
|
||||
|
@ -135,7 +201,8 @@ describe('EsqlQueryRuleTypeExpression', () => {
|
|||
],
|
||||
});
|
||||
getFields.mockResolvedValue([]);
|
||||
const result = render(
|
||||
|
||||
render(
|
||||
<EsqlQueryExpression
|
||||
unifiedSearch={unifiedSearchMock}
|
||||
ruleInterval="1m"
|
||||
|
@ -157,12 +224,12 @@ describe('EsqlQueryRuleTypeExpression', () => {
|
|||
}
|
||||
);
|
||||
|
||||
fireEvent.click(result.getByTestId('testQuery'));
|
||||
fireEvent.click(screen.getByTestId('testQuery'));
|
||||
await waitFor(() => expect(fetchFieldsFromESQL).toBeCalled());
|
||||
|
||||
expect(result.getByTestId('testQuerySuccess')).toBeInTheDocument();
|
||||
expect(result.getByText('Query matched 1 documents in the last 15s.')).toBeInTheDocument();
|
||||
expect(result.queryByTestId('testQueryError')).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('testQuerySuccess')).toBeInTheDocument();
|
||||
expect(screen.getByText('Query matched 1 documents in the last 15s.')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('testQueryError')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show error message if Test Query is throws error', async () => {
|
||||
|
|
|
@ -59,7 +59,7 @@ export const EsqlQueryExpression: React.FC<
|
|||
// The sourceFields param is ignored for the ES|QL type
|
||||
sourceFields: [],
|
||||
});
|
||||
const [query, setQuery] = useState<AggregateQuery>({ esql: '' });
|
||||
const [query, setQuery] = useState<AggregateQuery>(esqlQuery ?? { esql: '' });
|
||||
const [timeFieldOptions, setTimeFieldOptions] = useState([firstFieldOption]);
|
||||
const [detectedTimestamp, setDetectedTimestamp] = useState<string | undefined>(undefined);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
@ -75,18 +75,13 @@ export const EsqlQueryExpression: React.FC<
|
|||
[setRuleParams]
|
||||
);
|
||||
|
||||
const setDefaultExpressionValues = async () => {
|
||||
const setDefaultExpressionValues = () => {
|
||||
setRuleProperty('params', currentRuleParams);
|
||||
setQuery(esqlQuery ?? { esql: '' });
|
||||
if (esqlQuery) {
|
||||
if (esqlQuery.esql) {
|
||||
refreshTimeFields(esqlQuery);
|
||||
}
|
||||
}
|
||||
if (timeField) {
|
||||
setTimeFieldOptions([firstFieldOption, { text: timeField, value: timeField }]);
|
||||
if (esqlQuery?.esql) {
|
||||
refreshTimeFields(esqlQuery);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setDefaultExpressionValues();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
@ -154,20 +149,30 @@ export const EsqlQueryExpression: React.FC<
|
|||
isServerless,
|
||||
]);
|
||||
|
||||
const refreshTimeFields = async (q: AggregateQuery) => {
|
||||
const esqlDataView = await getESQLAdHocDataview(q.esql, dataViews);
|
||||
const indexPattern: string = esqlDataView.getIndexPattern();
|
||||
const currentEsFields = await getFields(http, [indexPattern]);
|
||||
const refreshTimeFields = useCallback(
|
||||
async (q: AggregateQuery) => {
|
||||
const fetchTimeFieldsData = async (queryObj: AggregateQuery) => {
|
||||
try {
|
||||
const esqlDataView = await getESQLAdHocDataview(queryObj.esql, dataViews);
|
||||
const indexPattern: string = esqlDataView.getIndexPattern();
|
||||
const currentEsFields = await getFields(http, [indexPattern]);
|
||||
const newTimeFieldOptions = getTimeFieldOptions(currentEsFields);
|
||||
const timestampField = esqlDataView.timeFieldName;
|
||||
return { newTimeFieldOptions, timestampField };
|
||||
} catch (e) {
|
||||
return { newTimeFieldOptions: [], timestampField: undefined };
|
||||
}
|
||||
};
|
||||
|
||||
const timeFields = getTimeFieldOptions(currentEsFields);
|
||||
setTimeFieldOptions([firstFieldOption, ...timeFields]);
|
||||
|
||||
const timestampField = esqlDataView.timeFieldName;
|
||||
if (timestampField) {
|
||||
setParam('timeField', timestampField);
|
||||
}
|
||||
setDetectedTimestamp(timestampField);
|
||||
};
|
||||
const { newTimeFieldOptions, timestampField } = await fetchTimeFieldsData(q);
|
||||
setTimeFieldOptions([firstFieldOption, ...newTimeFieldOptions]);
|
||||
if (!timeField && timestampField) {
|
||||
setParam('timeField', timestampField);
|
||||
}
|
||||
setDetectedTimestamp(timestampField);
|
||||
},
|
||||
[timeField, setParam, dataViews, http]
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue