diff --git a/public/app/features/alerting/unified/components/rules/RulesFilter.test.tsx b/public/app/features/alerting/unified/components/rules/RulesFilter.test.tsx index 4f7b1877828..536a496b198 100644 --- a/public/app/features/alerting/unified/components/rules/RulesFilter.test.tsx +++ b/public/app/features/alerting/unified/components/rules/RulesFilter.test.tsx @@ -1,10 +1,13 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; +import { TestProvider } from 'test/helpers/TestProvider'; +import { byLabelText, byRole } from 'testing-library-selector'; -import { logInfo } from '@grafana/runtime'; +import { locationService, logInfo, setDataSourceSrv } from '@grafana/runtime'; import { LogMessages } from '../../Analytics'; +import { MockDataSourceSrv } from '../../mocks'; import RulesFilter from './RulesFilter'; @@ -13,23 +16,68 @@ jest.mock('@grafana/runtime', () => { return { ...original, logInfo: jest.fn(), - DataSourcePicker: () => <>, }; }); -jest.mock('react-router-dom', () => ({ - useLocation: () => ({ - pathname: 'localhost:3000/example/path', - }), -})); +setDataSourceSrv(new MockDataSourceSrv({})); -jest.mock('../../utils/misc', () => ({ - getFiltersFromUrlParams: jest.fn(() => ({ dataSource: {}, alertState: {}, queryString: '', ruleType: '' })), -})); +const ui = { + stateFilter: { + firing: byRole('radio', { name: 'Firing' }), + normal: byRole('radio', { name: 'Normal' }), + }, + ruleType: { + alert: byRole('radio', { name: 'Alert' }), + }, + health: { + ok: byRole('radio', { name: 'Ok' }), + }, + searchInput: byLabelText('Search'), +}; + +beforeEach(() => { + locationService.replace({ search: '' }); +}); + +describe('RulesFilter', () => { + it('Should apply state filter to the search input', async () => { + const user = userEvent.setup(); + + render(, { wrapper: TestProvider }); + + await user.click(ui.stateFilter.firing.get()); + + expect(ui.searchInput.get()).toHaveValue('state:firing'); + }); + + it('Should apply multiple UI-based filters to the search input', async () => { + const user = userEvent.setup(); + + render(, { wrapper: TestProvider }); + + await user.click(ui.health.ok.get()); + await user.click(ui.ruleType.alert.get()); + await user.click(ui.stateFilter.normal.get()); + + expect(ui.searchInput.get()).toHaveValue('health:ok type:alerting state:inactive'); + }); + + it('Should combine UI filters and typed expressions', async () => { + const user = userEvent.setup(); + + render(, { wrapper: TestProvider }); + + await user.type(ui.searchInput.get(), 'cpu{Enter}'); + await user.click(ui.health.ok.get()); + await user.type(ui.searchInput.get(), ' usage'); + + expect(ui.searchInput.get()).toHaveValue('cpu health:ok usage'); + }); +}); describe('Analytics', () => { it('Sends log info when clicking alert state filters', async () => { - render(); + render(, { wrapper: TestProvider }); const button = screen.getByText('Pending'); diff --git a/public/app/features/alerting/unified/components/rules/RulesFilter.tsx b/public/app/features/alerting/unified/components/rules/RulesFilter.tsx index e2ec4b7103c..829dfe6f5fa 100644 --- a/public/app/features/alerting/unified/components/rules/RulesFilter.tsx +++ b/public/app/features/alerting/unified/components/rules/RulesFilter.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import React, { useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useForm } from 'react-hook-form'; import { DataSourceInstanceSettings, GrafanaTheme2, SelectableValue } from '@grafana/data'; @@ -69,6 +69,14 @@ const RulesFilter = ({ onFilterCleared = () => undefined }: RulesFilerProps) => const dataSourceKey = `dataSource-${filterKey}`; const queryStringKey = `queryString-${filterKey}`; + const searchQueryRef = useRef(null); + const { handleSubmit, register, setValue } = useForm<{ searchQuery: string }>({ defaultValues: { searchQuery } }); + const { ref, ...rest } = register('searchQuery'); + + useEffect(() => { + setValue('searchQuery', searchQuery); + }, [searchQuery, setValue]); + const handleDataSourceChange = (dataSourceValue: DataSourceInstanceSettings) => { updateFilters({ ...filterState, dataSourceName: dataSourceValue.name }); setFilterKey((key) => key + 1); @@ -106,10 +114,6 @@ const RulesFilter = ({ onFilterCleared = () => undefined }: RulesFilerProps) => setTimeout(() => setFilterKey(filterKey + 1), 100); }; - const searchQueryRef = useRef(null); - const { handleSubmit, register } = useForm<{ searchQuery: string }>({ defaultValues: { searchQuery } }); - const { ref, ...rest } = register('searchQuery'); - const searchIcon = ; return (
@@ -158,7 +162,7 @@ const RulesFilter = ({ onFilterCleared = () => undefined }: RulesFilerProps) => > +