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 @@ -5,10 +5,10 @@
* 2.0.
*/

import React from 'react';
import React, { PropsWithChildren } from 'react';
import { fireEvent, render, waitFor, screen, act } from '@testing-library/react';
import { I18nProvider } from '@kbn/i18n-react';
import { of, Subject } from 'rxjs';
import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers';
import { act } from 'react-dom/test-utils';
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';
Expand Down Expand Up @@ -106,6 +106,10 @@ const createDataPluginMock = () => {
return dataMock;
};

const AppWrapper = React.memo<PropsWithChildren<unknown>>(({ children }) => (
<I18nProvider>{children}</I18nProvider>
));

const dataMock = createDataPluginMock();
const dataViewMock = dataViewPluginMocks.createStartContract();
const unifiedSearchMock = unifiedSearchPluginMock.createStartContract();
Expand Down Expand Up @@ -151,76 +155,71 @@ describe('EsQueryRuleTypeExpression', () => {
timeWindowSize: [],
};

const wrapper = mountWithIntl(
<EsQueryExpression
unifiedSearch={unifiedSearchMock}
ruleInterval="1m"
ruleThrottle="1m"
alertNotifyWhen="onThrottleInterval"
ruleParams={alertParams}
setRuleParams={() => {}}
setRuleProperty={() => {}}
errors={errors}
data={dataMock}
dataViews={dataViewMock}
defaultActionGroupId=""
actionGroups={[]}
charts={chartsStartMock}
onChangeMetaData={() => {}}
/>
return await act(async () =>
render(
<EsQueryExpression
unifiedSearch={unifiedSearchMock}
ruleInterval="1m"
ruleThrottle="1m"
alertNotifyWhen="onThrottleInterval"
ruleParams={alertParams}
setRuleParams={() => {}}
setRuleProperty={() => {}}
errors={errors}
data={dataMock}
dataViews={dataViewMock}
defaultActionGroupId=""
actionGroups={[]}
charts={chartsStartMock}
onChangeMetaData={() => {}}
/>,
{
wrapper: AppWrapper,
}
)
);

const update = async () =>
await act(async () => {
await nextTick();
wrapper.update();
});

await update();
return wrapper;
}

test('should render EsQueryRuleTypeExpression with expected components', async () => {
const wrapper = await setup(defaultEsQueryExpressionParams);
expect(wrapper.find('[data-test-subj="indexSelectPopover"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="sizeValueExpression"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="queryJsonEditor"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="testQuerySuccess"]').exists()).toBeFalsy();
expect(wrapper.find('[data-test-subj="testQueryError"]').exists()).toBeFalsy();
expect(wrapper.find('[data-test-subj="thresholdExpression"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="forLastExpression"]').exists()).toBeTruthy();

const excludeHitsButton = wrapper.find(
'[data-test-subj="excludeHitsFromPreviousRunExpression"]'
);
expect(excludeHitsButton.exists()).toBeTruthy();
expect(excludeHitsButton.first().prop('checked')).toBeTruthy();
const result = await setup(defaultEsQueryExpressionParams);
expect(result.getByTestId('indexSelectPopover')).toBeInTheDocument();
expect(result.getByTestId('sizeValueExpression')).toBeInTheDocument();
expect(result.getByTestId('queryJsonEditor')).toBeInTheDocument();
expect(result.getByTestId('thresholdPopover')).toBeInTheDocument();
expect(result.getByTestId('forLastExpression')).toBeInTheDocument();
expect(result.queryByTestId('testQuerySuccess')).not.toBeInTheDocument();
expect(result.queryByTestId('testQueryError')).not.toBeInTheDocument();

expect(result.getByTestId('excludeHitsFromPreviousRunExpression')).toBeChecked();

const testQueryButton = wrapper.find('EuiButton[data-test-subj="testQuery"]');
expect(testQueryButton.exists()).toBeTruthy();
expect(testQueryButton.prop('disabled')).toBe(false);
expect(result.getByTestId('testQuery')).not.toBeDisabled();
});

test('should render Test Query button disabled if alert params are invalid', async () => {
const wrapper = await setup({
const result = await setup({
...defaultEsQueryExpressionParams,
timeField: null,
} as unknown as EsQueryRuleParams<SearchType.esQuery>);
const testQueryButton = wrapper.find('EuiButton[data-test-subj="testQuery"]');
expect(testQueryButton.exists()).toBeTruthy();
expect(testQueryButton.prop('disabled')).toBe(true);

expect(result.getByTestId('testQuery')).toBeDisabled();
});

test('should show excludeHitsFromPreviousRun unchecked by default', async () => {
const wrapper = await setup({
const result = await setup({
...defaultEsQueryExpressionParams,
excludeHitsFromPreviousRun: undefined,
} as unknown as EsQueryRuleParams<SearchType.esQuery>);
const excludeMatchesCheckBox = wrapper.find(
'EuiCheckbox[data-test-subj="excludeHitsFromPreviousRunExpression"]'
);
expect(excludeMatchesCheckBox.exists()).toBeTruthy();
expect(excludeMatchesCheckBox.prop('checked')).toBe(false);

expect(result.getByTestId('excludeHitsFromPreviousRunExpression')).not.toBeChecked();
});

test('should render EsQueryRuleTypeExpression with chosen size field', async () => {
const result = await setup({
...defaultEsQueryExpressionParams,
size: 0,
} as unknown as EsQueryRuleParams<SearchType.esQuery>);

expect(result.getByTestId('sizeValueExpression')).toHaveTextContent('Size 0');
});

test('should show success message if ungrouped Test Query is successful', async () => {
Expand All @@ -232,19 +231,14 @@ describe('EsQueryRuleTypeExpression', () => {
},
});
dataMock.search.search.mockImplementation(() => searchResponseMock$);
const wrapper = await setup(defaultEsQueryExpressionParams);
const testQueryButton = wrapper.find('button[data-test-subj="testQuery"]');
testQueryButton.simulate('click');
expect(dataMock.search.search).toHaveBeenCalled();
await act(async () => {
await nextTick();
wrapper.update();
});
expect(wrapper.find('[data-test-subj="testQuerySuccess"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="testQueryError"]').exists()).toBeFalsy();
expect(wrapper.find('EuiText[data-test-subj="testQuerySuccess"]').text()).toEqual(
`Query matched 1234 documents in the last 15s.`
);
await setup(defaultEsQueryExpressionParams);

fireEvent.click(screen.getByTestId('testQuery'));
await waitFor(() => expect(dataMock.search.search).toBeCalled());

expect(screen.getByTestId('testQuerySuccess')).toBeInTheDocument();
expect(screen.getByText('Query matched 1234 documents in the last 15s.')).toBeInTheDocument();
expect(screen.queryByTestId('testQueryError')).not.toBeInTheDocument();
});

test('should show success message if grouped Test Query is successful', async () => {
Expand Down Expand Up @@ -284,23 +278,18 @@ describe('EsQueryRuleTypeExpression', () => {
},
});
dataMock.search.search.mockImplementation(() => searchResponseMock$);
const wrapper = await setup({
await setup({
...defaultEsQueryExpressionParams,
termField: 'the-term',
termSize: 10,
});
const testQueryButton = wrapper.find('button[data-test-subj="testQuery"]');
testQueryButton.simulate('click');
expect(dataMock.search.search).toHaveBeenCalled();
await act(async () => {
await nextTick();
wrapper.update();
});
expect(wrapper.find('[data-test-subj="testQuerySuccess"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="testQueryError"]').exists()).toBeFalsy();
expect(wrapper.find('EuiText[data-test-subj="testQuerySuccess"]').text()).toEqual(
`Grouped query matched 5 groups in the last 15s.`
);

fireEvent.click(screen.getByTestId('testQuery'));
await waitFor(() => expect(dataMock.search.search).toBeCalled());

expect(screen.getByTestId('testQuerySuccess')).toBeInTheDocument();
expect(screen.getByText('Grouped query matched 5 groups in the last 15s.')).toBeInTheDocument();
expect(screen.queryByTestId('testQueryError')).not.toBeInTheDocument();
});

test('should show success message if Test Query is successful (with partial result)', async () => {
Expand All @@ -319,41 +308,31 @@ describe('EsQueryRuleTypeExpression', () => {
};
const searchResponseMock$ = new Subject();
dataMock.search.search.mockImplementation(() => searchResponseMock$);
const wrapper = await setup(defaultEsQueryExpressionParams);
const testQueryButton = wrapper.find('button[data-test-subj="testQuery"]');
await setup(defaultEsQueryExpressionParams);

testQueryButton.simulate('click');
expect(dataMock.search.search).toHaveBeenCalled();
await act(async () => {
fireEvent.click(screen.getByTestId('testQuery'));
await waitFor(() => expect(dataMock.search.search).toBeCalled());
await waitFor(() => {
searchResponseMock$.next(partial);
searchResponseMock$.next(complete);
searchResponseMock$.complete();
await nextTick();
wrapper.update();
});

expect(wrapper.find('[data-test-subj="testQuerySuccess"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="testQueryError"]').exists()).toBeFalsy();
expect(wrapper.find('EuiText[data-test-subj="testQuerySuccess"]').text()).toEqual(
`Query matched 1234 documents in the last 15s.`
);
expect(screen.getByTestId('testQuerySuccess')).toBeInTheDocument();
expect(screen.getByText('Query matched 1234 documents in the last 15s.')).toBeInTheDocument();
expect(screen.queryByTestId('testQueryError')).not.toBeInTheDocument();
});

test('should show error message if Test Query is throws error', async () => {
dataMock.search.search.mockImplementation(() => {
throw new Error('What is this query');
});
const wrapper = await setup(defaultEsQueryExpressionParams);
const testQueryButton = wrapper.find('button[data-test-subj="testQuery"]');

testQueryButton.simulate('click');
expect(dataMock.search.search).toHaveBeenCalled();
await act(async () => {
await nextTick();
wrapper.update();
});
await setup(defaultEsQueryExpressionParams);

fireEvent.click(screen.getByTestId('testQuery'));
await waitFor(() => expect(dataMock.search.search).toBeCalled());

expect(wrapper.find('[data-test-subj="testQuerySuccess"]').exists()).toBeFalsy();
expect(wrapper.find('[data-test-subj="testQueryError"]').exists()).toBeTruthy();
expect(screen.queryByTestId('testQuerySuccess')).not.toBeInTheDocument();
expect(screen.getByTestId('testQueryError')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const EsQueryExpression: React.FC<
timeWindowUnit: timeWindowUnit ?? DEFAULT_VALUES.TIME_WINDOW_UNIT,
threshold: threshold ?? DEFAULT_VALUES.THRESHOLD,
thresholdComparator: thresholdComparator ?? DEFAULT_VALUES.THRESHOLD_COMPARATOR,
size: size ? size : isServerless ? SERVERLESS_DEFAULT_VALUES.SIZE : DEFAULT_VALUES.SIZE,
size: size ?? (isServerless ? SERVERLESS_DEFAULT_VALUES.SIZE : DEFAULT_VALUES.SIZE),
esQuery: esQuery ?? DEFAULT_VALUES.QUERY,
aggType: aggType ?? DEFAULT_VALUES.AGGREGATION_TYPE,
groupBy: groupBy ?? DEFAULT_VALUES.GROUP_BY,
Expand Down Expand Up @@ -198,6 +198,7 @@ export const EsQueryExpression: React.FC<
<Fragment>
<EuiFormRow
fullWidth
data-test-subj="indexSelectPopover"
label={
<FormattedMessage
id="xpack.stackAlerts.esQuery.ui.selectIndexPrompt"
Expand All @@ -207,7 +208,6 @@ export const EsQueryExpression: React.FC<
>
<IndexSelectPopover
index={index}
data-test-subj="indexSelectPopover"
esFields={esFields}
timeField={timeField}
errors={errors}
Expand Down
Loading