Skip to content

Commit

Permalink
[ResponseOps][Alerts] Fix DSL filter issues in search bar (#193623)
Browse files Browse the repository at this point in the history
## Summary

Resolves #183908
Resolves #192557

This PR fixes an issue of DSL filter in
<details><summary>Search bar in Alerts page of Stack
management</summary>
<img width="1237" alt="image"
src="https://github.com/user-attachments/assets/b9b380d2-80a7-4754-95f2-6b6831923c4d">
</details> 

<details><summary>Search bar in Alerts page of Observability</summary>
<img width="1237" alt="image"
src="https://github.com/user-attachments/assets/68ceb97f-b958-47f4-b356-757cbafd9170">
</details> 

<details><summary>Search bar in "If alerts matches query" action
filter</summary>
<img width="1281" alt="image"
src="https://github.com/user-attachments/assets/1f99ca43-c4b5-4f52-b50f-914f1e205c5b">
</details> 

<details><summary>Search bar in Maintenance window page</summary>
<img width="1272" alt="image"
src="https://github.com/user-attachments/assets/ffaa317d-c14b-45a2-9d02-00f7a10239ab">
</details> 


### Checklist
- [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

### How to verify
- Create a DSL filter in above mentioned pages
- Verify that filter is applied properly

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
js-jankisalvi and kibanamachine authored Oct 13, 2024
1 parent d6e2b26 commit 122647b
Show file tree
Hide file tree
Showing 12 changed files with 686 additions and 60 deletions.
171 changes: 171 additions & 0 deletions packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
import { Filter, FilterStateStore } from '@kbn/es-query';
import { ToastsStart } from '@kbn/core-notifications-browser';
import { useLoadRuleTypesQuery, useRuleAADFields, useAlertsDataView } from '../common/hooks';
import { AlertsSearchBar } from '.';
import { HttpStart } from '@kbn/core-http-browser';

const mockDataPlugin = dataPluginMock.createStartContract();
jest.mock('@kbn/kibana-utils-plugin/public');
jest.mock('../common/hooks');

jest.mocked(useAlertsDataView).mockReturnValue({
isLoading: false,
dataView: {
title: '.alerts-*',
fields: [
{
name: 'event.action',
type: 'string',
aggregatable: true,
searchable: true,
},
],
},
});

jest.mocked(useLoadRuleTypesQuery).mockReturnValue({
ruleTypesState: {
isInitialLoad: false,
data: new Map(),
isLoading: false,
error: null,
},
authorizedToReadAnyRules: false,
hasAnyAuthorizedRuleType: false,
authorizedRuleTypes: [],
authorizedToCreateAnyRules: false,
isSuccess: false,
});

jest.mocked(useRuleAADFields).mockReturnValue({
aadFields: [],
loading: false,
});

const unifiedSearchBarMock = jest.fn().mockImplementation((props) => (
<button
data-test-subj="querySubmitButton"
onClick={() => props.onQuerySubmit({ dateRange: { from: 'now', to: 'now' } })}
type="button"
>
{'Hello world'}
</button>
));

const toastsMock = { toasts: { addWarning: jest.fn() } } as unknown as ToastsStart;
const httpMock = {
post: jest.fn(),
} as unknown as HttpStart;

describe('AlertsSearchBar', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('renders correctly', async () => {
render(
<AlertsSearchBar
rangeFrom="now/d"
rangeTo="now/d"
query=""
onQuerySubmit={jest.fn()}
onFiltersUpdated={jest.fn()}
appName={'test'}
featureIds={['observability', 'stackAlerts']}
unifiedSearchBar={unifiedSearchBarMock}
toasts={toastsMock}
http={httpMock}
dataService={mockDataPlugin}
/>
);
expect(await screen.findByTestId('querySubmitButton')).toBeInTheDocument();
});

it('calls onQuerySubmit correctly', async () => {
const onQuerySubmitMock = jest.fn();

render(
<AlertsSearchBar
rangeFrom="now/d"
rangeTo="now/d"
query=""
onQuerySubmit={onQuerySubmitMock}
onFiltersUpdated={jest.fn()}
unifiedSearchBar={unifiedSearchBarMock}
toasts={toastsMock}
http={httpMock}
dataService={mockDataPlugin}
appName={'test'}
featureIds={['observability', 'stackAlerts']}
/>
);

fireEvent.click(await screen.findByTestId('querySubmitButton'));

await waitFor(() => {
expect(onQuerySubmitMock).toHaveBeenCalled();
});
});

it('calls onFiltersUpdated correctly', async () => {
const onFiltersUpdatedMock = jest.fn();
const filters: Filter[] = [
{
meta: {
negate: false,
alias: null,
disabled: false,
type: 'custom',
key: 'query',
},
query: { bool: { filter: [{ term: { 'kibana.alert.rule.consumer': 'stackAlerts' } }] } },
$state: { store: FilterStateStore.APP_STATE },
},
];

const newUnifiedSearchBarMock = jest.fn().mockImplementation((props) => (
<button
data-test-subj="filtersSubmitButton"
onClick={() => props.onFiltersUpdated(filters)}
type="button"
>
{'Hello world'}
</button>
));

render(
<AlertsSearchBar
rangeFrom="now/d"
rangeTo="now/d"
query=""
onQuerySubmit={jest.fn()}
onFiltersUpdated={onFiltersUpdatedMock}
unifiedSearchBar={newUnifiedSearchBarMock}
toasts={toastsMock}
http={httpMock}
dataService={mockDataPlugin}
appName={'test'}
featureIds={['observability', 'stackAlerts']}
/>
);

fireEvent.click(await screen.findByTestId('filtersSubmitButton'));

await waitFor(() => {
expect(onFiltersUpdatedMock).toHaveBeenCalledWith(filters);
expect(mockDataPlugin.query.filterManager.setFilters).toHaveBeenCalledWith(filters);
});
});
});
9 changes: 6 additions & 3 deletions packages/kbn-alerts-ui-shared/src/alerts_search_bar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ export const AlertsSearchBar = ({
http,
toasts,
unifiedSearchBar,
dataViewsService,
dataService,
}: AlertsSearchBarProps) => {
const [queryLanguage, setQueryLanguage] = useState<QueryLanguageType>('kuery');
const { dataView } = useAlertsDataView({
featureIds,
http,
toasts,
dataViewsService,
dataViewsService: dataService.dataViews,
});
const { aadFields, loading: fieldsLoading } = useRuleAADFields({
ruleTypeId,
Expand Down Expand Up @@ -119,7 +119,10 @@ export const AlertsSearchBar = ({
displayStyle: 'inPage',
showFilterBar,
onQuerySubmit: onSearchQuerySubmit,
onFiltersUpdated,
onFiltersUpdated: (newFilters) => {
dataService.query.filterManager.setFilters(newFilters);
onFiltersUpdated?.(newFilters);
},
onRefresh,
showDatePicker,
showQueryInput: true,
Expand Down
4 changes: 2 additions & 2 deletions packages/kbn-alerts-ui-shared/src/alerts_search_bar/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { Filter } from '@kbn/es-query';
import type { ValidFeatureId } from '@kbn/rule-data-utils';
import type { ToastsStart, HttpStart } from '@kbn/core/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { DataViewsContract } from '@kbn/data-views-plugin/common';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';

export type QueryLanguageType = 'lucene' | 'kuery';

Expand Down Expand Up @@ -41,5 +41,5 @@ export interface AlertsSearchBarProps {
http: HttpStart;
toasts: ToastsStart;
unifiedSearchBar: UnifiedSearchPublicPluginStart['ui']['SearchBar'];
dataViewsService: DataViewsContract;
dataService: DataPublicPluginStart;
}
Loading

0 comments on commit 122647b

Please sign in to comment.